2013年4月25日木曜日

Fragment in Fragment 時の注意点

Android 4.2 で Fragment in Fragment 用の API が用意されました。
NestedFragments : Android 4.2

また、Support Library でも同様の機能が提供されています。

今回、この API を使ってちょっとはまったのでメモしておきます。

構成としては

Activity の ActionBar の
Tab
 |
Fragment(A) の
ViewPager
 |
Fragment(B)

のようになっています。

Fragment(A)では、getChildFragmentManager() をつかって素直に ViewPager に Adapter をセットしているだけです。

Fragment(A) public class TabFragment3 extends SherlockFragment { ViewPager mPager; @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_pager, parent, false); mPager = (ViewPager) v.findViewById(R.id.pager); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager()); mPager.setAdapter(adapter); } public class MyPagerAdapter extends FragmentPagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { PageFragment fragment = new PageFragment(); return fragment; } @Override public int getCount() { return 3; } } } Activity では、ActionBar に普通に Tab をセットしています。 public class MainActivity extends SherlockFragmentActivity implements TabListener { TabFragment1 mTabFragment1; TabFragment2 mTabFragment2; TabFragment3 mTabFragment3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mTabFragment1 = new TabFragment1(); mTabFragment2 = new TabFragment2(); mTabFragment3 = new TabFragment3(); ActionBar actionBar = getSupportActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.addTab(actionBar.newTab() .setText(R.string.tab1) .setTabListener(this)); actionBar.addTab(actionBar.newTab() .setText(R.string.tab2) .setTabListener(this)); actionBar.addTab(actionBar.newTab() .setText(R.string.tab3) .setTabListener(this)); } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { int position = tab.getPosition(); switch (position) { case 0: ft.replace(android.R.id.content, mTabFragment1); break; case 1: ft.replace(android.R.id.content, mTabFragment2); break; case 2: ft.replace(android.R.id.content, mTabFragment3); break; } } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } } こうすると、Fragment(A)のタブを開いて、一旦別のタブを開いてから、戻ると落ちるんです!
ViewPager に Adapter をセットしているところで

04-25 10:46:44.949: E/AndroidRuntime(21011): FATAL EXCEPTION: main
04-25 10:46:44.949: E/AndroidRuntime(21011): java.lang.IllegalStateException: Activity has been destroyed

とか言われます。

onTabSelected() で replace する Fragment(A) のインスタンスを毎回作り直すようにしたら落ちなくなりました! public class MainActivity extends SherlockFragmentActivity implements TabListener { ... @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { int position = tab.getPosition(); switch (position) { case 0: ft.replace(android.R.id.content, mTabFragment1); break; case 1: ft.replace(android.R.id.content, mTabFragment2); break; case 2: mTabFragment3 = new TabFragment3(); ft.replace(android.R.id.content, mTabFragment3); break; } } } はまったわー。。。。