Activity > Fragment > ViewPager > Fragmentという構成にするとViewPager内のFragmentでonActivityResultが呼ばれなくなってしまう。
また、Activity直下にFragmentが複数あると、想定していないFragmentのonActivityResultが呼ばれてしまう。
例:
Activity > (DrawerFragment + (ParentFragment > ViewPager > ChildFragment))↑このような構成の時、ViewPager内のChildFragmentからstartActivityForResultを呼ぶと、ChildFragmentのonActivityResultが呼ばれないだけでなく、DrawerFragmentのonActivityResultが呼ばれてしまったりする。
なお、ParentFragmentのonActivityResultも呼ばれない。
どのFragmentからActivityが呼ばれたかは、そのFragmentが属するFragmentManager内のIndexで管理しているようだ。
ネストされたFragmentからActivityを呼ぶと、FragmentのIndexは親FragmentのFragmentManager(getChildFragmentManagerで取得するFragmentManager)から取得される。
しかし、Activity#onActivityResultで呼び出し元のFragmentを判定する時は、ActivityのFragmentManagerから対応するFragmentを取得しようとするようである。そのため、見当違いのFragmentのonActivityResultが呼ばれてしまう。
なお、サポートライブラリではそもそも親Fragmentから子FragmentのonActivityResultを呼ぶ機能はない模様。
よくわからないFragmentのonActivityResultが呼ばれてしまう件は、とりあえず無視。そのFragmentにonActivityResultを実装していなければ問題ないし、実装している場合もきちんと条件分岐していれば問題ない。
子FragmentのonActivityResultに関しては、下記のようにして対応する
Fragmentで結果を受け取りたい場合は、親FragmentのstartActivityForResultを呼ぶ。FragmentではonActivityResultを受け取れるので、親FragmentのonActivityResult内で、すべての子FragmentのonActivityResultを手動で呼ぶ// BaseFragment.java
protected void callChildOnActivityResult(FragmentManager fm,
int requestCode, int resultCode, Intent data) {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size() > 0) {
for (Fragment fragment : fragments) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}上記のようなメソッドを用意し、必要な箇所(親FragmentのonActivityResult)で呼ぶとよさげ。
// FooActivity.java
public static void startActivity(Fragment fragment) {
Intent intent = new Intent(fragment.getActivity(), FooActivity.class);
// 親Fragmentがあれば親Fragmentから呼ぶ
Fragment parentFragment = fragment.getParentFragment();
if (parentFragment == null) {
fragment.startActivityForResult(intent, "fragment_content");
} else {
parentFragment.startActivityForResult(intent, "fragment_content");
}
}Activityを開始するときはこんな感じ。