M
M
makerkz2013-12-02 19:21:53
Android
makerkz, 2013-12-02 19:21:53

How to solve error with ListView and AsyncTask in Android?

Good day to all! There was (although it did not disappear anywhere) such a problem when updating the adapter data. For users, it occurs quite often - in 2 days, in general, about 200 crashes for ~ 15,000 users. I would like to know how to fix it.

log cat
FATAL EXCEPTION
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131099702, class android.widget.ListView) with Adapter(class devz.tim.vk.helpers.WallAdapter)]
       at android.widget.ListView.layoutChildren(ListView.java:1544)
       at android.widget.AbsListView.onLayout(AbsListView.java:2300)
       at android.view.View.layout(View.java:14072)
       at android.view.ViewGroup.layout(ViewGroup.java:4607)
       at android.widget.RelativeLayout.onLayout(RelativeLayout.java:948)
       at android.view.View.layout(View.java:14072)
       at android.view.ViewGroup.layout(ViewGroup.java:4607)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
       at android.view.View.layout(View.java:14072)
       at android.view.ViewGroup.layout(ViewGroup.java:4607)
       at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1655)
       at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1513)
       at android.widget.LinearLayout.onLayout(LinearLayout.java:1426)
       at android.view.View.layout(View.java:14072)
       at android.view.ViewGroup.layout(ViewGroup.java:4607)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
       at android.view.View.layout(View.java:14072)
       at android.view.ViewGroup.layout(ViewGroup.java:4607)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
       at android.view.View.layout(View.java:14072)
       at android.view.ViewGroup.layout(ViewGroup.java:4607)
       at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1997)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1818)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1115)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4526)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
       at android.view.Choreographer.doCallbacks(Choreographer.java:555)
       at android.view.Choreographer.doFrame(Choreographer.java:525)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
       at android.os.Handler.handleCallback(Handler.java:615)
       at android.os.Handler.dispatchMessage(Handler.java:92)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:4921)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
       at dalvik.system.NativeStart.main(NativeStart.java)


Data is updated via AsyncTask. in doInBackground(); the data is updated in the LinkedHashMap, and then in onPostExecute(); the adapter itself is updated.
AsyncTask
public class LoadWall extends AsyncTask<Void, Void, Void> {
    public int[] OWNER_ID;
    public int OFFSET;
    public int COUNT;
    public boolean REFRESH;
    public Context context;
    public Activity activity;
    public ArrayList<String> LINKS = new ArrayList<String>();
    public ArrayList<LinkedHashMap<String, String>> LIST;
    public WallAdapter ADAPTER;
    public ListView LISTVIEW;
    JSONObject obj;
    public ArrayList<LinkedHashMap<String, String>> tempList;

    public LoadWall(int[] OWNER_ID, int OFFSET, int COUNT, boolean REFRESH,
            Context context, ArrayList<LinkedHashMap<String, String>> LIST,
            WallAdapter ADAPTER, ListView LISTVIEW) {
        this.OWNER_ID = OWNER_ID;
        this.OFFSET = OFFSET;
        this.COUNT = COUNT;
        this.REFRESH = REFRESH;
        this.context = context;
        this.LIST = LIST;
        this.ADAPTER = ADAPTER;
        this.LISTVIEW = LISTVIEW;
        activity = (Activity) context;
    }

    @Override
    protected void onPreExecute() {
        activity.setProgressBarIndeterminateVisibility(true);
        activity.setProgressBarVisibility(true);
        if (REFRESH == true){
            LIST.clear();
            if(tempList != null){
                tempList.clear();
            }
            LISTVIEW.requestLayout();
            ADAPTER.notifyDataSetChanged();
        }
        AppHelper.refreshAttacher.setRefreshing(true);
        tempList = new ArrayList<LinkedHashMap<String, String>>();
        tempList = LIST;
    };

    @Override
    protected Void doInBackground(Void... params) {
            LINK = "here is link for json";
            obj = Helpers.getJson(LINK);
            if (obj != null) {
                Helpers.refreshListView(obj, tempList);
            }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        if(obj==null){
            Toast.makeText(context, context.getString(R.string.loadfailed), Toast.LENGTH_LONG).show();
        }
        LIST = tempList;
        ADAPTER.notifyDataSetChanged();
        activity.setProgressBarIndeterminateVisibility(false);
        activity.setProgressBarVisibility(false);
        AppHelper.refreshAttacher.setRefreshComplete();
        super.onPostExecute(result);
    };
}

The solution on StackOverflow didn't help.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Anton, 2013-12-03
@makerkz

We cling to the following line of Logcat:
Next, we see the following in AsyncTask:

@Override
    protected Void doInBackground(Void... params) {
            LINK = "here is link for json";
            obj = Helpers.getJson(LINK);
            if (obj != null) {
                Helpers.refreshListView(obj, tempList);
            }
        return null;
    }

Helpers.refreshListView(obj, tempList); called in the doInBackground() method which is executed in the background thread!
Move the refreshListView() call to the onProgressUpdate() method of the AsyncTask (which is already running on the UI Thread!):
protected Void doInBackground(Void... params) {
    // ...
    publishProgress(new MyProgress(obj, tempList));
    // ...
}

protected void onProgressUpdate(MyProgress... progress) {
    if (progress.size() > 0) {
        Helpers.refreshListView(progress[0].getObj(), progress[0].getTempList());
    }
}

---
Upd: More - because. you need to pass both obj and tempList to UIThread - then you need to make a wrapper class for them, for example like this - (each class in its own file, of course)
public class LoadWall extends AsyncTask<Void, MyProgress, Void> {
    // ...
    @Override
    protected Void doInBackground(Void... params) {
        // ...
        publishProgress(new MyProgress(obj, tempList));
        // ...
    }

    @Override
    protected void onProgressUpdate(MyProgress... progress) {
        if (progress.size() > 0) {
            Helpers.refreshListView(progress[0].getObj(), progress[0].getTempList());
        }
    }
    // ...
}

/**
 * Используется для передачи прогресса в UI-Thread
 */
public class MyProgress {

    private final Object obj;
    private final ArrayList<LinkedHashMap<String, String>> tempList;

    public MyProgress(Object obj, ArrayList<LinkedHashMap<String, String>> tempList) {
        this.obj      = obj;
        this.tempList = tempList;
    }

    public Object getObj() {
        return obj;
    }

    public ArrayList<LinkedHashMap<String, String>> getTempList() {
        return tempList;
    }
}

B
bimeg, 2013-12-03
@bimeg

Remove the last line in onPreExecute.
This one
tempList = LIST;

R
Roman, 2013-12-02
@WNeZRoS

It is not very clear from the code how everything works, but the last two lines in onPreExecute look strange.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question