Java – RecyclerView with cursor loader is too slow when updating frequently

RecyclerView with cursor loader is too slow when updating frequently… here is a solution to the problem.

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:

  1. I registered an “observer” in the content parser query() method: cursor.setNotificationUri(getContext().getContentResolver(), uri);
  2. When I update/insert/delete in the content parser, I notify the observer: getContext().getContentResolver().notifyChange(uri, null); So onLoaderReset() 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.

Related Problems and Solutions