2013-04-25
Activity.onAttachFragment() does not work with ChildFragmentManager
Fragment#getChildFragmentManager()で取得したFragmentManagerで管理しているFragmentはアタッチされても Activity.onAttachFragment(Fragment) が呼ばれないという話。
(尚、本エントリーの内容はサポートパッケージでしか現象の確認と調査を行っていません)
おしごとでChildFragmentManagerによるFragment in Fragmentで、このひと(Y.A.M の 雑記帳 Fragment in Fragment 時の注意点)とともにはまったのでメモ。
弊社ではAndroid開発にgoogle-guice、daggerなどのDIフレームワークを使っていまして、(はじめてのDependency Injection)でやっているようにライフサイクルメソッドのコールバックを作成して、コールバック内でインジェクションしています。
コールバックでやっている理由は、DIされるオブジェクト自身が自らDIコンテナのインジェクションメソッドを呼び出すよりも、コールバックを受け取った別の誰かがDIするほうが利点があるからで、それはいいとして、ともかく。
- ActivityへのインジェクションはActivity.onCreate(Bundle)
- FragmentへのインジェクションはActivity.onAttachFragment(Fragment)
でやっていたわけです。
しかし、ViewPagerを持つFragmentからChildFragmentManagerで管理されたViewPager内のFragmentでは、なぜかActivity.onAttachFragment(Fragment)がコールバックされないという現象が発生しました。
結果はご想像どおり、@Inject されるべきところに何もインジェクションされていないので、依存オブジェクトのメソッド呼び出した瞬間、ぬるぽ ガッですよね。
というわけで、原因を追ってみました。
結論を言うと、FragmentManagaer.getChildFragmentManager()で取得したFragmentManagerに管理されたFragmentオブジェクトはmParentFragmentフィールドに親(そのFragmentを管理するためにFragmentManagaer.getChildFragmentManager()を呼び出したFragmentオブジェクト)が設定されています。
mParentFragmentフィールドに親が設定されていると、Activity.onAttachFragment(Fragment) は呼ばれません。
FragmentManagerの該当箇所のコードは次のようになっています。
if (f.mParentFragment == null) { mActivity.onAttachFragment(f); }
仕方がないので、インジェクションするためのコールバックをActivity.onAttachFragment(Fragment)からFragment.attach(Activity)に変更して対応しました。
DIのためにActiviy.onAttachFragment(Fragment) を使わなくても、Fragmentのインスタンスの参照を得たり、リスナーをごにょごにょしたりするためにonAttachFragment(Fragment)を使っている人は注意が必要です。
以上です。
