FragmentActivity
私は s である 2 つのタブを持っていますListFragment
。それぞれListFragment
にコールバックがあります。
(注:気づいた場合、この質問のほとんどは、私自身の質問Callback after orientation change become nullから再ハッシュされていますが、これは回転とは関係がないため別の質問ですが、私の希望は私の実際の問題を理解することですコールバック。)
コールバックの例
http://developer.android.com/training/basics/fragments/communicating.htmlで説明されているように、コールバックはonAttach(...)メソッド内で関連付けられています。
OnTab1Listener mTab1Callback;
public interface OnTab1Listener {
public void onTab1Update();
}
@Override
public void onAttach(Activity activity) {
Log.d(TAG, "onAttach");
super.onAttach(activity);
try {
mTab1Callback = (OnTab1Listener)activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnTab1Listener");
}
}
後で、FragmentActivity
正常に動作するこのコールバックで と通信します。
アプリケーションがしばらくの間バックグラウンドに送信された後、アプリケーションを前面に移動して、コールバックを使用する何かをトリガーすると、コールバックがnullになり、アプリがクラッシュします。バックグラウンドでシステムがガベージコレクションを実行すると、これが発生すると思います。
通常の実行中に正常に動作する呼び出しの例を次に示します。
public void toggleEnabled(View v) {
Log.d(TAG, "toggleEnabled");
// null pointer here
mTab1Callback.onTab1Update();
}
質問
- ガベージ コレクションが行われている場合、 mTab1Callbackガベージ コレクションが行われ、復元されないのはなぜですか? 私の印象は、参照の一部がガベージ コレクションされている場合、onAttach(...)
Activity
を含め、ライフサイクルとFragment
ライフサイクルが再起動するというものでした。 - これはどのように適切に修正されていますか?
サンプルアプリ
この動作を示すサンプル アプリケーションを作成しました。完全なソースコードはこちらhttp://www.2shared.com/file/kkgFejUq/broken_example.html
アプリのスタック トレースの例
FATAL EXCEPTION: main
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:3591)
at android.view.View.performClick(View.java:4084)
at android.widget.CompoundButton.performClick(CompoundButton.java:100)
at android.view.View$PerformClick.run(View.java:16966)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
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:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at android.view.View$1.onClick(View.java:3586)
... 12 more
Caused by: java.lang.NullPointerException
at com.example.myapp.Tab2.toggleEnabled(Tab1.java:87)
at com.example.myapp.MainActivity.onClick(MainActivity.java:50)
... 15 more
ここにTab1.java:87があります
mTab1Callback.onTab1Update();
これは、アプリをバックグラウンドに移動させ、ゲームを少しプレイしたり、音楽を再生したりするなど、他のことをしばらく行ってフォアグラウンドに戻し、チェックボックスのいずれかをクリックすると、null ポインターになります。
必要に応じて、アプリのアイコンをランチャーに配置してそこから起動し、他のアプリをしばらく実行した後、フォアグラウンドに移動します。これはクラッシュするときです。
また、エミュレーターでクラッシュさせることはできません。実際のハードウェアのみです。電話がコンピューターに接続されている場合はクラッシュする可能性が低く、テスト中にプラグを抜いた場合は簡単にクラッシュするようです.
TabsAdapterはこれと関係がありますか?
また、これはファイルに含まれているSherlockActionBarを使用します。MyAppのライブラリとして使用する必要があります。
アップデート
getActivity()がnullであることがわかり始めました。ローテーションまたはバックグラウンドで長期間実行した後、null である唯一の場所は、コールバックを起動するtoggleEnabled()関数内です。
これは、原因がもはや存在しないMainActivity
a を参照していることを示しているようです。Fragment
スペースのコードを組み合わせると、これは基本的に、 in をクリックした後に toggleEnabled() 関数を参照する方法です。(完全なコードについては、添付の例を参照してください)CheckBox
Tab1
public void onClick(View v) {
Tab1 tab = (Tab1)mTabsAdapter.getItem(0);
tab.toggleEnabled(v);
}
だから私はgetItem(...)TabsAdapter
に従うために掘り下げました。ここにあるもの
プライベート ArrayList mFragments = new ArrayList(); // タブなどを設定するコード @Override public Fragment getItem(int position) { Fragment frag = mFragments.get(position); if (frag.getActivity() == null) Log.d(TAG, "getItem: Activity is null");
return mFragments.get(position);
}
回転前に何が起こるか、getActivity()はnull ではありません。回転すると、getActivity()はnullになります。これは、私が信じてFragment
いる適切なものを再現していないことを示しているようです。Context
しかし、これは、この種のことに関する私の知識が終わるところです。
静的にすることはできmFragments
ますが、それは正しい解決策ではないように感じます。
Fragment
が適切に取り付けられていない理由を知っている人はいますActivity
か?