7

ページング可能な 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);
4

2 に答える 2

4

ListView に次のようなものを追加してみてください。

    @Override
protected void layoutChildren() {
    try {
        super.layoutChildren();
    } catch (IllegalStateException e) {
        ZLog.e(LOG, "This is not realy dangerous problem");
    }
}

ヘッダービューまたはフッタービュー ListView を追加し、notifyDataSetChanged() を実行すると、mItemCount が実際のアダプターのアイテム数に変更されますが、右側はヘッダーカウントとフッターカウントを追加した偽のアイテムカウントを返します。

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/widget/ListView.java?av=f#1538

于 2013-03-08T08:16:14.537 に答える
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();
}
于 2013-03-07T15:12:03.853 に答える