Skip to content Skip to sidebar Skip to footer

Recyclerview Blocking Ui Thread During Updates

There are more than 200 items in my list. RecyclerView is updated regularly (Every 10 seconds) . RecyclerView blocking ui thread for few seconds during updates. I'm using notifyD

Solution 1:

You do not need to call notifyDataSetChanged, it's an expensive operation your whole RecyclerView will completely redraw, rebind etc.

As the doc says:

This event does not specify what about the data set has changed, forcing any observers to assume that all existing items and structure may no longer be valid. LayoutManagers will be forced to fully rebind and relayout all visible views.

All you need to do is loop through every position and if needed update desired item otherwise do nothing or skip.

What you should do:

As you are updating your whole view first you need to compare your (visible) adapter's List<Asset> with new List<Asset> and retrieve only those items which you need to be update, once you have the list loop through updated list and update your adapter's view by using viewAdapter.notifyItemChanged(position).

Solution 2:

Perform the action to update the adapter as:

publicvoidrefreshAssetList(List<Asset> newAssetList){
        getActivity().runOnUiThread(newRunnable() {
            @Overridepublicvoidrun() {
                recyclerViewAdapter.setAssetList(newAssetList);
                recyclerViewAdapter.notifyDataSetChanged();
            }
        }); 
}

Solution 3:

After some research I found DiffUtil class for updating list.

From the documentation :

DiffUtil is a utility class that can calculate the difference between two lists and output a list of update operations that converts the first list into the second one.

DiffUtil needs new list and old list. It only updates changing items in list. I created AssetDiffUtil class as below :

publicclassAssetDiffUtilextendsDiffUtil.Callback {

    privatefinal List<Asset> oldList;
    privatefinal List<Asset> newList;

    publicAssetDiffUtil(List<Asset> oldList, List<Asset> newList) {
        this.oldList = oldList;
        this.newList = newList;
    }

    @OverridepublicintgetOldListSize() {
        return oldList.size();
    }

    @OverridepublicintgetNewListSize() {
        return newList.size();
    }

    @OverridepublicbooleanareItemsTheSame(int oldItemPosition, int newItemPosition) {
        return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
    }

    @OverridepublicbooleanareContentsTheSame(int oldItemPosition, int newItemPosition) {
        finalLastoldItem= oldList.get(oldItemPosition).getLast();
        finalLastnewItem= newList.get(newItemPosition).getLast();
        return oldItem.getDate().equals(newItem.getDate());
    }

    @Nullable@Overridepublic Object getChangePayload(int oldItemPosition, int newItemPosition) {
        // Implement method if you're going to use ItemAnimatorreturnsuper.getChangePayload(oldItemPosition, newItemPosition);
    }
}

Then I added swapItems method for refreshing list in AssetListRecyclerViewAdapter class.

publicvoidswapItems(List<Asset> newAssetList) {
        final DiffUtil.DiffResultdiffResult= DiffUtil.calculateDiff(newAssetDiffUtil(this.assetList, newAssetList));
        this.assetList.clear();
        this.assetList.addAll(newAssetList);
        diffResult.dispatchUpdatesTo(this);
    }

That's it. But my problem still exist. Before using DiffUtil freezing time 4 seconds . Now, after using DiffUtil freezing time is 2 seconds. Unfortunately this is not a definitive solution for my problem.

Solution 4:

use notifyItemRangeChanged instead of notifyDataSetChanged , also sometimes when using progress bars libraries like SpinKitView it increases the freezing time

loadMoreProgress.visibility = View.VISIBLE
            homeViewModel.latestBars.observe(viewLifecycleOwner, Observer {
                latestBarTests.addAll(it)
                latestBarsAdapter.notifyItemRangeChanged(
                    latestBarTests.size - it.size,
                    latestBarTests.size
                )
            })

Post a Comment for "Recyclerview Blocking Ui Thread During Updates"