Android, ListView IllegalStateException: “The content of the adapter has changed but ListView did not receive a notification”

后端 未结 25 2114
执念已碎
执念已碎 2020-11-22 16:59

What I want to do: run a background thread which calculates ListView contents and update ListView partially, while results are calculated.

W

相关标签:
25条回答
  • 2020-11-22 17:36

    I had the same issue.

    I was adding items to my ArrayList outside the UI thread.

    Solution: I have done both, adding the items and called notifyDataSetChanged() in the UI thread.

    0 讨论(0)
  • 2020-11-22 17:36

    I solved this by have 2 Lists. One list I use for only the adapter, and I do all data changes/updates on the other list. This allows me to do updates on one list in a background thread, and then update the "adapter" list in the main/UI thread:

    List<> data = new ArrayList<>();
    List<> adapterData = new ArrayList();
    
    ...
    adapter = new Adapter(adapterData);
    listView.setAdapter(adapter);
    
    // Whenever data needs to be updated, it can be done in a separate thread
    void updateDataAsync()
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                // Make updates the "data" list.
                ...
    
                // Update your adapter.
                refreshList();
            }
        }).start();
    }
    
    void refreshList()
    {
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                adapterData.clear();
                adapterData.addAll(data);
                adapter.notifyDataSetChanged();
                listView.invalidateViews();
            }
        });
    }
    
    0 讨论(0)
  • 2020-11-22 17:36

    i haved same problem when add new data in lazy image loader i just put

             adapter.notifyDataSetChanged();
    

    in

           protected void onPostExecute(Void args) {
            adapter.notifyDataSetChanged();
            // Close the progressdialog
            mProgressDialog.dismiss();
             }
    

    hope it helps you

    0 讨论(0)
  • 2020-11-22 17:38

    Several days ago I met the same problem and causes several thousands of crash per day, about 0.1% of users meet this situation. I tried setVisibility(GONE/VISIBLE) and requestLayout(), but crash count only decreases a little.

    And I finally solved it. Nothing with setVisibility(GONE/VISIBLE). Nothing with requestLayout().

    Finally I found the reason is I used a Handler to call notifyDataSetChanged() after update data, which may lead to a sort of:

    1. Updates data to a model object(I call it a DataSource)
    2. User touches listview(which may call checkForTap()/onTouchEvent() and finally calls layoutChildren() )
    3. Adapter gets data from model object and call notifyDataSetChanged() and update views

    And I made another mistake that in getCount(), getItem() and getView(), I directly use fields in DataSource, rather than copy them to the adapter. So finally it crashes when:

    1. Adapter updates data which last response gives
    2. When next response back, DataSource updates data, which causes item count change
    3. User touches listview, which may be a tap or a move or flip
    4. getCount() and getView() is called, and listview finds data is not consistent, and throws exceptions like java.lang.IllegalStateException: The content of the adapter has changed but.... Another common exception is an IndexOutOfBoundException if you use header/footer in ListView.

    So solution is easy, I just copy data to adapter from my DataSource when my Handler triggers adapter to get data and calls notifyDataSetChanged(). The crash now never happens again.

    0 讨论(0)
  • 2020-11-22 17:41

    Please try one of these solutions :

    1. Sometimes, if you add new object to data list in a thread (or doInBackground method), this error will occur. The solution is : create a temporary list and do adding data to this list in thread(or doInBackground), then do copying all data from temporary list to the list of adapter in UI thread (or onPostExcute)

    2. Make sure all UI updates are called in UI thread.

    0 讨论(0)
  • 2020-11-22 17:41

    i had the same problem. finally i got the solution

    before updating listview, if the soft keypad is present close it first. after that set data source and call notifydatasetchanged().

    while closing keypad internally listview will update its ui. it keep calling till closing keypad. that time if data source change it willl throw this exception. if data is updating in onActivityResult, there is a chance for same error.

     InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
    
            view.postDelayed(new Runnable() {
                @Override
                public void run() {
                    refreshList();
                }
            },100L);
    
    0 讨论(0)
提交回复
热议问题