RecyclerView notifyItemInserted IllegalStateException

21,519

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();
    }
Share:
21,519
user1333057
Author by

user1333057

Updated on August 22, 2020

Comments

  • user1333057
    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 from onLayoutChildren from LayoutManager, i tried overriding it and calling notifyItemInserted after its super but i got the same exception

    how can i achieve my goal?

  • pjanecze
    pjanecze over 9 years
    That'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
    XxGoliathusxX over 8 years
    Omg that helped me so much. But does this process require much capacity or is it inefficient?
  • Rafael
    Rafael over 8 years
    I don't know that much.
  • Iman Akbari
    Iman Akbari about 8 years
    this works, thanks. I shouldn't have upgraded to the new support library.
  • Abdul Waheed
    Abdul Waheed about 7 years
    but it does not let me create handler object due to its abstraction :(
  • Shayan Amani
    Shayan Amani about 7 years
    @AbdulWaheed please have a look at my code snippet below for your case.
  • Abdul Waheed
    Abdul Waheed about 7 years
    Ahh find out the reason.I was importing wrong class
  • Harco
    Harco over 6 years
    Scrapped or attached views may not be recycled. isScrap:false isAttached:true =(