4

私はサポート ライブラリを使用しており、OnClick イベント中にフラグメントのビューの 1 つによって呼び出されるメソッドを実装するフラグメント (「MyFragment」と呼びます) があります。OnClickListener は、次のように OnActivityCreate メソッドで設定されます。

@Override
public void onActivityCreated(Bundle inState) {
    super.onActivityCreated(inState);

    ViewGroup base = (ViewGroup) getView();
    TextView tv = (TextView) base.findViewById(R.id.monografiat);
    tv.setOnClickListener(new OnClickListener() {                            
        @Override
        public void onClick(View v) {
            showStuff(); // MyFragment:150
        }
    });
}

showStuff() は、フラグメントのビューの変更をトリガーします。これは、アイテムの可視性を更新するのと同じくらい簡単です。

private void showStuff() {  //MyFragment:95
    ViewGroup base = (ViewGroup) getView();
    LinearLayout ll = (LinearLayout) base.findViewById(R.id.someview); // MyFragment:97
    ll.setVisibility(View.VISIBLE);
}

私のテストではすべてが正常に動作し、ほとんどのユーザーについても同じことが言えますが、今日、Google Play 開発者のコ​​ンソールから 1 つの ANR レポートを受け取りました。次の行に NullPointerException があるユーザーに対してアプリがクラッシュしたことが示されています。

LinearLayout ll = (LinearLayout) base.findViewById(R.id.someview);

つまり、次のことを意味します。

ViewGroup base = (ViewGroup) getView();

null を返しました。これはレポートです:

java.lang.NullPointerException
    at mypackage.MyFragment.showStuff(MyFragment.java:97)
    at mypackage.MyFragment.access$0(MyFragment.java:95)
    at mypackage.MyFragment$2.onClick(MyFragment.java:150)
    at android.view.View.performClick(View.java:2538)
    at android.view.View$PerformClick.run(View.java:9152)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:3687)
    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:842)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)

問題のある行を次のように囲むだけで、問題を修正しました(または、再現方法がないためだと思います...)。

if(base != null) {
}

私の最善の推測は、onDestroyView が MyFragment で呼び出された後にコールバックがスケジュールされたため、getView() が null を返すことです。

それでも、私はこのバグに非常に困惑しているので、この問題についての洞察をお願いします。

  1. 私のhypotesysが正しいと仮定すると、レイアウトが存在しないときにOnClickコールバックが実行されるのは正常ですか、それともこの動作をバグと見なすことができますか(正直に言うと、クリックしたときにビューが明らかにそこにあったのに、なぜそれが死ぬ必要があるのですか)自分)?

  2. この問題は、サポート ライブラリ (最終バージョン、2013 年 5 月 13 日) を使用していることに関連していますか?

  3. バグではなく、何か不足している場合は、関連するドキュメントを教えてください。

ご清聴ありがとうございました!

4

1 に答える 1

1

Gingerbread までは、が から切り離されたViewときに、クリックを実行するためのコールバックがメッセージ キューから削除されないというバグがクリック メカニズムにありました。これは ICS (またはおそらく Honeycomb) で修正されています。したがって、Gingerbread 以下をサポートしていて、が切り離されたときに削除される他の参照にクリック リスナーがアクセスする場合は、切り離し時にクリック リスナーも必ず削除する必要があります。ViewWindowView

これは、 だけでなく、あらゆる種類のクリック リスナーに適用されることに注意してくださいOnClickListener。ただし、コールバックは最初から適切に削除されているため、ロング クリック リスナーには適用されません。

于 2014-12-16T04:49:40.517 に答える