Android ListView with paging crashes
<p>I have pageable ListView and its rows are being loaded asynchronously while scrolling down and sometimes the app just crashes. It's not happening on Android 2.3.3 but does happen on Android 4.0 and above.</p>

<p>Here is my stack trace:</p>

<pre><code>03-07 15:23:02.450: D/AndroidRuntime(1545): Shutting down VM
03-07 15:23:02.450: W/dalvikvm(1545): threadid=1: thread exiting with uncaught exception (group=0x40ccb930)
03-07 15:23:02.455: E/AndroidRuntime(1545): FATAL EXCEPTION: main
03-07 15:23:02.455: E/AndroidRuntime(1545): 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(2131099953, class com.ui.PaginableListView) with Adapter(class android.widget.HeaderViewListAdapter)]
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.widget.ListView.layoutChildren(ListView.java:1544)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4042)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.view.Choreographer.doCallbacks(Choreographer.java:562)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.view.Choreographer.doFrame(Choreographer.java:531)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.os.Handler.handleCallback(Handler.java:725)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.os.Handler.dispatchMessage(Handler.java:92)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.os.Looper.loop(Looper.java:137)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at android.app.ActivityThread.main(ActivityThread.java:5191)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at java.lang.reflect.Method.invokeNative(Native Method)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at java.lang.reflect.Method.invoke(Method.java:511)
03-07 15:23:02.455: E/AndroidRuntime(1545):         at com.android.internal.os.ZygoteInit$MethodAnd
</code></pre>

<p>It's part of the code, probably not very helpful ;/</p>

<pre><code>protected DataResponse doInBackground(IRequest... reqs) {
    IRequest req = reqs[0];
    CancelStateHolder cancelStateHolder = new CancelStateHolder() {
        @Override
        public boolean isCancelled() {
            return DataRequestTask.this.isCancelled();
        }
    };

    if (cacheKey != null) {
        try {
            CacheDogpileProtector.getInstance().acquire(cacheKey);
        } catch (InterruptedException e) {
            cancel(true);
            ZLog.printStackTrace(e);
        }
    }

    reqExec.setParentTask(this);
    DataResponse resp = reqExec.execute(req, cancelStateHolder,
    cacheContext, cacheKey);
    if (resp == null) {
        Log.d(LOG, "resp == null");
    }
    return resp;
}

@Override
protected void onPostExecute(DataResponse result) {
    super.onPostExecute(result);
    ZLog.d(LOG, "override onPostExecute");
    try {
        if (result.getJsonResponse() == null) {
            ZLog.i(LOG, "json is NULL (probably connection problem)   response text: " + result.getResponseText());
            throw new NASAException(R.string.exception_io);
        }
        ConsumptionStatus consumption = ConsumptionStatus.REQUEST_NOT_CONSUMED;
        if (onZadaneRequestCompletedListener != null) {
            consumption = onZadaneRequestCompletedListener.onZadaneRequestCompleted(PaginableListView.this, request, result);
        }

        switch (consumption) {
            case REQUEST_CONSUMED:
                 break;
            case REQUEST_UPDATE_METADATA:
                 wrapAndUpdate(result.getJsonResponse(), true);
                 break;
            case REQUEST_NOT_CONSUMED:
                 wrapAndUpdate(result.getJsonResponse(), false);
                 break;
         }
         if (onZadaneRequestCompletedListener != null) {
             onZadaneRequestCompletedListener.onZadaneRequestCompletedAfterWrap(PaginableListView.this, request, result, lastFetchedPage);
         }
         setOnRefreshListener(properOnRefreshListener);
     } catch (NASAException e) {
         DialogHandler.handleError(mContext, e.getMessage(mContext));
     } finally {
         removeFooterView(footerView);
         actualTask = null;
     }
}

};
actualTask.executeCached(activity, cacheContext, request);
</code></pre>
