9

ListActivityユーザーが選択したアイテムのコンテンツで新しいアクティビティを開いた後、元に戻ると、この例外が発生します。アイス クリーム サンドイッチでのみ発生します。

これはトレースです:

 java.lang.IllegalArgumentException: The observer is null.
    at android.database.Observable.unregisterObserver(Observable.java:59)
    at android.widget.BaseAdapter.unregisterDataSetObserver(BaseAdapter.java:42)
    at android.widget.AbsListView.onDetachedFromWindow(AbsListView.java:2373)
    at android.view.View.dispatchDetachedFromWindow(View.java:9756)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2274)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272)
    at android.view.ViewRootImpl.dispatchDetachedFromWindow(ViewRootImpl.java:2227)
    at android.view.ViewRootImpl.doDie(ViewRootImpl.java:3679)
    at android.view.ViewRootImpl.die(ViewRootImpl.java:3667)
    at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:320)
    at android.view.WindowManagerImpl$CompatModeWrapper.removeViewImmediate(WindowManagerImpl.java:139)
    at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3144)
    at android.app.ActivityThread.access$1200(ActivityThread.java:122)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1179)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4340)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    at dalvik.system.NativeStart.main(Native Method)

私のコードはスタックに記載されていないので、本当に困惑しており、ダーティキャッチを実行することはできません:/

DataSetObserverアクティビティが作成されたときにのみ匿名を登録しています。また、アクティビティは ActivityGroup 内に埋め込まれています (これは 4.0 で廃止されましたが、まだサポートされているはずです)。

新しいOSでこの問題が発生した人はいますか?

前もって感謝します。


アップデート:

わかりました。解決方法はわかりませんが、問題の原因を見つけたと思います。

内部AbsListView.onDetachedFromWindow()には次のものがあります。

if (mAdapter != null) { // Android code added on ICS
    mAdapter.unregisterDataSetObserver(mDataSetObserver);
    mDataSetObserver = null;
}

オブザーバーが登録解除されると、無効になります。問題は、何らかの理由で、ICS で 2 回呼び出されることです。クラスで行うように、削除操作内で null パラメータをチェックするのは少しばかげていると思います。Observable

public void unregisterObserver(T observer) { // Android code
    if (observer == null) {
        throw new IllegalArgumentException("The observer is null.");
    }
    synchronized(mObservers) {
        int index = mObservers.indexOf(observer);
        if (index == -1) {
            throw new IllegalStateException("Observer " + observer + " was not registered.");
        }
        mObservers.remove(index);
    }
}

なぜ彼らはそれを無視しないのですか?

public void unregisterObserver(T observer) { // Android code
    synchronized(mObservers) {
        mObservers.remove(observer);
    }
}
4

2 に答える 2

11

この問題はAndroid4.0.3で導入され、オブザーバブルが複数回解放されたときに例外をスローするようにObservableクラスが変更されました。バグとして報告されており、http ://code.google.com/p/android/issues/detail?id=22946で読むことができます。

この問題を回避する最も簡単な方法は、基礎となるアダプターをラップし、複数のリリースを回避することです。

@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
  if (observer != null) {
    super.unregisterDataSetObserver(observer);
  }
} 

ただし、これはすべての場合に機能するわけではありません。たとえば、ExpandableListViewには、アクセスできない内部アダプターがあります。ここでの別の解決策は、ExpandableListViewをラップして、例外をキャッチすることです。この解決策は私のために働きました、そして私はまだどんな副作用も見つけませんでした。

public class PatchedExpandableListView extends ExpandableListView {

  public PatchedExpandableListView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  protected void onDetachedFromWindow() {
    try {
      super.onDetachedFromWindow();
    } catch(IllegalArgumentException iae) {
      // Workaround for http://code.google.com/p/android/issues/detail?id=22751
    }
  }
}
于 2012-02-07T09:34:12.973 に答える
3

私は自分のクラスのどれもトレースに記載されていないと考えるというばかげた間違いをしましたが、LoadingDataViewはそのうちの1つです。元のトレースには表示されませんが、関連する別のトレースには表示されません。

そのクラス内には、インシデントが発生している場所である匿名のArrayAdapterがあるため、回避策としてこれを追加しました。

@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
    if (observer != null) {
        super.unregisterDataSetObserver(observer);
    }
}

そして、なぜこのメソッドが2回呼び出されたのかはまだわかりませんが、現在は機能しているようです。

ただし、今のところ、可能な限りフラグメントを使用します;)

于 2011-12-15T10:58:31.440 に答える