RecyclerView with cursor loader is too slow when updating frequently
I’m using LoaderManager.LoaderCallbacks to get a podcast feed from a database and display it in RecyclerView. In My Content Providers:
- I registered an “observer” in the content parser query() method:
cursor.setNotificationUri(getContext().getContentResolver(), uri);
- When I update/insert/delete in the content parser, I notify the observer: getContext().
getContentResolver().notifyChange(uri, null);
SoonLoaderReset()
fires when needed
Then I have a service DownloadManager, which updates the progress of my ongoing download to the database every second. The loader keeps loading data from the database, and I can see the progress of each downloaded fragment in the UI.
I think
this is a wrong way to notify changes and very, very slow, but I can’t think of a better solution right now. Can you suggest any effective solutions for RecyclerView and download progress?
I use a custom activity for RecyclerView
public class MyActivity
implements LoaderManager.LoaderCallbacks<Cursor> {
private RecyclerView mRecyclerView;
private MyCustomRecyclerViewAdapter mAdapter;
...
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(this,
myDataUri, null, null, null, null
);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
...
}
My custom adapter
public class MyCustomRecyclerViewAdapter
extends RecyclerView.Adapter<EpisodeAdapter.AudioAdapterViewHolder> {
...
public void swapCursor(Cursor newCursor) {
mCursor = newCursor;
notifyDataSetChanged();
}
...
}
Solution
ReclyclerView
is more efficient when the adapter has a stable ID (specifically the notifyDataSetChanged()
method).
If your data has IDs (e.g. from a database), you should really consider having your adapter use setHasStableIds(true) and overrides correctly getItemId( int position) .
I’m not sure if this will completely solve your problem, but it’s definitely a good practice.