我有可分页的ListView,它的行在向下滚动时异步加载,有时候应用程序崩溃了。它不会发生在Android 2.3.3上,但确实发生在Android 4.0及更高版本上。
这是我的堆栈跟踪:
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
这是代码的一部分,可能不是很有帮助; /
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);
答案 0 :(得分:4)
您可以尝试将这样的内容添加到ListView:
@Override
protected void layoutChildren() {
try {
super.layoutChildren();
} catch (IllegalStateException e) {
ZLog.e(LOG, "This is not realy dangerous problem");
}
}
如果添加headerview或footerview ListView,并且当你通知notifyDataSetChanged()时,它会将mItemCount更改为真实适配器的项目数,但右侧将返回添加了headercount和footercount的虚假itemcount:
答案 1 :(得分:0)
正如您的堆栈跟踪所示,您无法使用后台线程更新适配器的内容。由于您使用的是AsyncTask
,因此修复此操作非常简单。不要在doInBackground
中更新适配器,而是在onPostExecute
更新它。
以下是这可能是什么样子。
@Override
protected Object doInBackground(Object... params) {
Object results = getResults(); /* Replace with your own result fetching code */
return results;
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
/* Update your adapter here using the returned results. */
myAdapter.addNewData(result);
myAdapter.notifyDataSetChanged();
}