1

FragmentActivityから前後にナビゲーションを操作しているときに例外を受け取り、 ListView にカスタム ローダーからロードされたデータ (ローカルの sqlite データベースからロードされています) が含まれており、その処理方法がわかりません...

スタックトレースは次のとおりです。

Uncaught exception: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.PriceTracerActivity}: java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.CartFragmentActivity}: java.util.ConcurrentModificationException
java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.PriceTracerActivity}: java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.CartFragmentActivity}: java.util.ConcurrentModificationException
    at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3106)
    at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3171)
    at android.app.ActivityThread.access$2100(ActivityThread.java:132)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1071)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:150)
    at android.app.ActivityThread.main(ActivityThread.java:4293)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Unable to destroy activity {com.snyer.bestprice/com.snyer.bestprice.CartFragmentActivity}: java.util.ConcurrentModificationException
    at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3106)
    at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:2994)
    at android.app.LocalActivityManager.dispatchDestroy(LocalActivityManager.java:625)
    at android.app.ActivityGroup.onDestroy(ActivityGroup.java:85)
    at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3088)
    ... 11 more
Caused by: java.util.ConcurrentModificationException
    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
    at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:42)
    at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:54)
    at android.support.v4.widget.CursorAdapter.swapCursor(CursorAdapter.java:352)
    at com.snyer.bestprice.CartFragmentActivity.onLoaderReset(CartFragmentActivity.java:412)
    at android.support.v4.app.LoaderManagerImpl$LoaderInfo.destroy(LoaderManager.java:337)
    at android.support.v4.app.LoaderManagerImpl.doDestroy(LoaderManager.java:773)
    at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:318)
    at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3088)
    ... 15 more

mCartCursorAdapter.swapCursor(null);このコード フラグメントの行で例外が発生します(CartFragmentActivity.java:412):

public void onLoaderReset(Loader<Cursor> loader) {
    switch (loader.getId()) {
    case LOADER_CART_LIST_ID:
        mCartListCursorAdapter.swapCursor(null);
        break;

    case LOADER_CART_CONTENTS_ID:
        mCartCursorAdapter.swapCursor(null);
        break;
    }
}

この例外を削除するには、ここで何ができますか?

4

3 に答える 3

4

sdkソースはコメントとして良いヒントを与えます:

Android 4.0.4では、次のようになります。

public void notifyInvalidated() {
    synchronized(mObservers) {
        for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onInvalidated();
        }
    }
}

以前のバージョンでは、次のようになりました。

 synchronized (mObservers) {
        for (DataSetObserver observer : mObservers) {
            observer.onInvalidated();
        }
    }

4.0.4ソースには、onChangeメソッドの同じ変更に関して次のコメントがあります。

// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.

ただし、オブザーバーのArrayListを違法な方法で操作していることに気づいていません。これは後のAPIで解決され、アプリへの影響は考えられないため、ログエントリなどの例外を無視するだけだと思います。

于 2012-11-09T13:04:14.883 に答える
0

onLoaderReset()によってバックグラウンド スレッドで呼び出されている可能性がありますLoaderrunOnUiThread()または同様のメカニズムを使用して、swapCursor()呼び出しをメイン アプリケーション スレッドに移動してみてください。

于 2012-10-08T11:19:54.210 に答える
0

DataSetObservable「適切な」バージョンの SDK からアプリにコピーして使用するのが最も速い方法です。DataSetObservable次のようになります。

public class DataSetObservable extends Observable<DataSetObserver> {
/**
 * Invokes {@link DataSetObserver#onChanged} on each observer.
 * Called when the contents of the data set have changed.  The recipient
 * will obtain the new contents the next time it queries the data set.
 */
public void notifyChanged() {
    synchronized(mObservers) {
        // since onChanged() is implemented by the app, it could do anything, including
        // removing itself from {@link mObservers} - and that could cause problems if
        // an iterator is used on the ArrayList {@link mObservers}.
        // to avoid such problems, just march thru the list in the reverse order.
        for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onChanged();
        }
    }
}

/**
 * Invokes {@link DataSetObserver#onInvalidated} on each observer.
 * Called when the data set is no longer valid and cannot be queried again,
 * such as when the data set has been closed.
 */
public void notifyInvalidated() {
    synchronized (mObservers) {
        for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onInvalidated();
        }
    }
} 

あなたの場合、BaseAdapter もソース コードからコピーする必要があります。DataSetObservableそして、あなたの appに Android を変更しますDataSetObservable

于 2013-10-07T16:35:43.087 に答える