Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Suggestion required for Update recycler view on item selected from spinner

I am new to recycler view. My requirement is as follows: - I have to call a web service that will give two arrays. One with data I need to show in the list. For this purpose, I am using RecyclerView. The other array is of statuses, which I am showing in spinner. This web service is paginated. I have added pagination and it is working fine. - When user selects some other element from the spinner, again I have to make a web service call and recycler view data should change. Currently, in case of pagination I am doing following, once I get more data from the successive pages:

mAccountListingsAdapter.notifyItemRangeInserted(mAccountListingsAdapter.getItemCount(), mListings.size() - 1);

And, when I change data from spinner, I am doing following:

mListings.clear();//Clear the data set

mAccountListingsAdapter.notifyDataSetChanged();//Call notify data set changed on recycler view adapter

getAccountListings();//Fetch new data from the web service and display in recycler view

But, it is suggested that, instead of calling notifyDataSetChanged() directly on recycler view adapter, one should call specific notifyXXX method, to avoid performance and animations issues.

So, I am under doubt, if I am doing right to notify recycler view adapter in onItemSelected() of spinner, or it should be changed.

P.S. I tried following in the onItemSelected:

int size = mListings.size();
mListings.clear();
mAccountListingsAdapter.notifyItemRangeRemoved(0, size - 1);

But then it crashed, with following exception:

03-02 12:59:41.046: E/AndroidRuntime(4270): java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 4(offset:0).state:5
like image 393
Nitish Avatar asked Mar 02 '16 07:03

Nitish


2 Answers

I think notifyItemRangeRemoved is the correct method to use here, but the value you are passing for second parameter is wrong. As per the doc, the second parameter is number of items removed from data set, what you are passing is the position of last item removed.

enter image description here

So the below code should work fine

int size = mListings.size();
mListings.clear();
mAccountListingsAdapter.notifyItemRangeRemoved(0, size);

For more info refer : http://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemRangeRemoved(int,%20int)

like image 77
Abhishek V Avatar answered Nov 14 '22 23:11

Abhishek V


First of all, the method definition for notifyItemRangeRemoved (int, int) is:

public final void notifyItemRangeRemoved (int positionStart, int itemCount)

The second argument is the count, not positionEnd. In your case you are passing size - 1 as the second argument, when it should be size itself.

int size = mListings.size();
mListings.clear();
// should be notifyItemRangeRemoved(0, size)
mAccountListingsAdapter.notifyItemRangeRemoved(0, size - 1);

Second, notifyDataSetChanged() is frowned upon because it triggers a rebind and relayout of all visible views. In your case, where the number of visible items is zero, I don't see why notifyDataSetChanged() would degrade performance. If you are animating the removal of items, go with notifyItemRangeRemoved(0, size). Else, its quite alright to use notifyDataSetChanged() over here.

like image 21
Vikram Avatar answered Nov 15 '22 01:11

Vikram