Hari Swaminathan Hari Swaminathan - 1 month ago 10
Android Question

Android: HorizontalScrollview content not getting updated Dynamically

We are facing an issue with HorizontalScrollview content not getting updated dynamically. At the first time call to the below function set the scrollview content correctly (Called from onCreate). But from the next time onwards the layout is not getting updated (basically calling the function after some new downloads are done on the background service). playlist_scroll is the HorizontalScrollView in which we are having the LinearLayout playlist_content to which the items (inflated from partial_main_playlist) are added.

HorizontalScrollView playlist_scroll = (HorizontalScrollView) findViewById(R.id.playlist_scroll);
LinearLayout playlist_content = (LinearLayout) findViewById(R.id.playlist_content);

private void setPlaylistNameScroll(List<Playlist> result) {
if (result != null && result.size() > 0) {
playlist_row_position = 0;
playlists = result;
playlist_content.removeAllViews();
for (Playlist playlist : playlists) {
playlist_ll = (LinearLayout) getLayoutInflater().inflate(R.layout.partial_main_playlist, playlist_content, false);
playlist_ll.setTag(playlist.getId());
Log.d(TAG, "setPlaylistNameScroll - playlist " + playlist.getName());
if (border != null && !border.equals("")) {
playlist_ll.setBackgroundColor(Color.parseColor("#" + border));
}
playlist_row = (LinearLayout) playlist_ll.findViewById(R.id.playlist_row);
LinearLayout.LayoutParams playlist_row_params = (LinearLayout.LayoutParams) playlist_row.getLayoutParams();
playlist_row_params.width = playlist_row_width;
playlist_row_params.height = playlist_row_height;
playlist_row.setLayoutParams(playlist_row_params);
playlist_row_item = (LinearLayout) playlist_ll.findViewById(R.id.playlist_row_item);
if (playlist_bg_bitmap_draw != null) {
playlist_row_item.setBackground(playlist_bg_bitmap_draw);
}
playlist_tv = (TextView) playlist_ll.findViewById(R.id.playlist_tv);
String _playlist_name = playlist.getName();
playlist_tv.setText(_playlist_name);
playlist_tv.setTextColor(Color.parseColor("#" + playlist_title_color));
playlist_ll.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
v.startAnimation(btn_click_animation);
break;
}
return false;
}
});
playlist_content.addView(playlist_row, playlist_row_position++);

}
playlist_scroll.post(new Runnable() {
public void run() {
if(playlist_content.getParent() != null)
{
((ViewGroup)playlist_content.getParent()).removeView(playlist_content);
}
playlist_scroll.addView(playlist_content);
}
});
}
}


the partial_main_playlist.xml is as follows

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:id="@+id/playlist_row"
android:clickable="true"
android:onClick="playlistClicked"
android:background="@color/colorDefaultBg">
<LinearLayout
android:id="@+id/playlist_row_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="@dimen/resource_row_margin"
android:orientation="horizontal">
<TextView
android:id="@+id/playlist_tv"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:textAlignment="center"
android:ellipsize="marquee"
android:maxLines="1"
android:textStyle="bold"
android:gravity="center"
android:layout_gravity="center_vertical"
android:text="Playlist"
android:textColor="@color/colorDefaultText"
android:textSize="@dimen/playlist_scroll_title_font" />
<ImageView
android:id="@+id/playlist_status"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="0.1"
android:layout_gravity="end"
android:gravity="center"
android:scaleType="center"
android:visibility="invisible"
android:src="@drawable/shuffle"/>
</LinearLayout>
</LinearLayout>


We have referred the answer here and implemented the above code

setPlaylistNameScroll method is invoked from the DownloadService on ReceiveResult like this

public void onReceiveResult(int resultCode, Bundle resultData) {
String error;
switch (resultCode) {
case DownloadService.STATUS_RUNNING:
media_syncing = true;
Log.d(TAG, "DownloadService.STATUS_RUNNING");
break;
case DownloadService.STATUS_FINISHED:
Log.d(TAG, "DownloadService.STATUS_FINISHED");
setPlaylistNameScroll(databaseHandler.getDevicePlaylists(device_id, playlist_ordering));
break;
case DownloadService.STATUS_ERROR:
media_syncing = false;
error = resultData.getString(Intent.EXTRA_TEXT);
Log.d(TAG, "DownloadService.STATUS_ERROR " + error);
break;
case DownloadService.STATUS_STOPPED:
media_syncing = false;
error = resultData.getString(Intent.EXTRA_TEXT);
Log.d(TAG, "DownloadService.STATUS_STOPPED " + error);
break;
}
}

Answer

We have read in google doc, other tutorials that any Update to the horizontalscrollview content should happen from the UI thread. So we set the receiver like

mReceiver = new DownloadResultReceiver(new Handler());     
mReceiver.setReceiver(this);

As per my understanding "new Handler()" will make sure that the result receiver method calls will execute in the UI thread. But unfortunately this was not the case in our case atleast in Android 5.1.1 API Level 22, other version we haven't observed this issue. Finally we ended up in something like a runnable which will contantly check if there is a new version if so it will update the horizontal Scrollview

Runnable refreshChecker = new Runnable() {
    @Override
    public void run() {
        try {
            int save_media_called = databaseHandler.getSave_media_called();                               
            if (save_media_called_log != save_media_called && save_media_called != 0) {                    setPlaylistNameScroll(databaseHandler.getDevicePlaylists(device_id, playlist_ordering));
                save_media_called_log = save_media_called;
            }
        } finally {
            refreshHandler.postDelayed(refreshChecker, refresh_check_interval);
            refresh = true;
        }
    }
};
Comments