RecyclerView notifyItemInserted IllegalStateException
Solution 1
Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
};
handler.post(r);
My sample code where I call adapter.notifyDataSetChanged(); from Activity
Solution 2
It's also worth noting the JavaDoc on the RecyclerView.isComputingLayout()
method that triggers this exception :
/**
* Returns whether RecyclerView is currently computing a layout.
* <p>
* If this method returns true, it means that RecyclerView is in a lockdown state and any
* attempt to update adapter contents will result in an exception because adapter contents
* cannot be changed while RecyclerView is trying to compute the layout.
* <p>
* It is very unlikely that your code will be running during this state as it is
* called by the framework when a layout traversal happens or RecyclerView starts to scroll
* in response to system events (touch, accessibility etc).
* <p>
* This case may happen if you have some custom logic to change adapter contents in
* response to a View callback (e.g. focus change callback) which might be triggered during a
* layout calculation. In these cases, you should just postpone the change using a Handler or a
* similar mechanism.
*
* @return <code>true</code> if RecyclerView is currently computing a layout, <code>false</code>
* otherwise
*/
public boolean isComputingLayout() {
return mLayoutOrScrollCounter > 0;
}
The salient phrase being :
In these cases, you should just postpone the change using a Handler or a similar mechanism.
In my case, I was modifying the adapter contents from another thread, which was (occasionally) causing a collision. Shifting the update to a Handler on the UI thread naturally solves this.
Solution 3
Using a Handler
for adding items and calling notify...()
from this Handler
fixed the issue for me.
Solution 4
Neat and easy way:
recyclerView.post(new Runnable() {
@Override
public void run() {
adapter.notifyDataSetChanged();
}
});
Explanation: You use your RecyclerView
instance and inside the post method a new Runnable
added to the message queue. The runnable will be run on the user interface thread. This is a limit for Android to access the UI thread from background (e.g. inside a method which will be run in a background thread).
Solution 5
Try this
if (!recyclerView.isComputingLayout()) {
recyclerView.notifyDataSetChanged();
}
user1333057
Updated on August 22, 2020Comments
-
user1333057 almost 4 years
i am porting my adapter into
RecyclerView.Adapter
what i want to achieve: when the user scrolls down near the end i want to start fetch data, i also want to add i ProgressBar view at the end to let the user know more data is coming.
the way i implemented this in my BaseAdapter: on
getView
in the view requested in near the end, i would start fetching more data, call notifyDataSetChanged (to get the ProgressBar view to show) and only then return the view needed forgetView
.what i tried doing in RecyclerView.Adapter: i tried to do the same thing basically, this time in the method
onBindViewHolder
,but if i try and call
notifyItemInserted
inside this method i get the following exception:IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
what i tried: i noticed that
onBindViewHolder
gets called fromonLayoutChildren
fromLayoutManager
, i tried overriding it and callingnotifyItemInserted
after itssuper
but i got the same exceptionhow can i achieve my goal?
-
pjanecze over 9 yearsThat's the right answer, you cannot change item while it is setting (with calling onBindViewHolder). In that case you have to call notifyItemInserted at the end of current loop by calling Handler.post()
-
XxGoliathusxX over 8 yearsOmg that helped me so much. But does this process require much capacity or is it inefficient?
-
Rafael over 8 yearsI don't know that much.
-
Iman Akbari about 8 yearsthis works, thanks. I shouldn't have upgraded to the new support library.
-
Abdul Waheed about 7 yearsbut it does not let me create handler object due to its abstraction :(
-
Shayan Amani about 7 years@AbdulWaheed please have a look at my code snippet below for your case.
-
Abdul Waheed about 7 yearsAhh find out the reason.I was importing wrong class
-
Harco over 6 yearsScrapped or attached views may not be recycled. isScrap:false isAttached:true =(