2013年7月12日金曜日

ViewPager の Fragment を画面回転後も保持する方法

FragmentPagerAdapter を使って各画面に Fragment を使う場合、ある画面の Fragment インスタンスを保持しておいてそれに対して処理を行うということがあります。
  1. public class MainActivity extends SherlockFragmentActivity implements LibraryListener, DrawerListener {  
  2.   
  3.     private MainFragment mMainFragment;  
  4.   
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.   
  10.         ViewPager viewPager = (ViewPager) findViewById(R.id.pager);  
  11.         viewPager.setAdapter(new MainPagerAdapter(getSupportFragmentManager()));  
  12.     }  
  13.   
  14.     public class MainPagerAdapter extends FragmentPagerAdapter {  
  15.   
  16.         public MainPagerAdapter(FragmentManager fm) {  
  17.             super(fm);  
  18.         }  
  19.   
  20.         @Override  
  21.         public Fragment getItem(int position) {  
  22.             switch (position) {  
  23.                 case 0:  
  24.                     return (mMainFragment = new MainFragment());  
  25.                 case 1:  
  26.                     return new SubFragment();  
  27.             }  
  28.   
  29.             return null;  
  30.         }  
  31.   
  32.         @Override  
  33.         public int getCount() {  
  34.             return 2;  
  35.         }  
  36.     }  
  37.   
  38.     private void hoge() {  
  39.         mMainFragment.fuga();  
  40.     }  
  41. }  
このような場合、画面回転後に hoge() を呼ぶと mMainFragment が null なので NPE になります。
なぜ mMainFragment が null になるかというと、FragmentPagerAdapter が一度 getItem() で生成した Fragment を再利用してくれるので、画面回転時に getItem() が呼ばれないからです。

画面回転後も mMainFragment に以前のインスタンスを保持させるには、次のように onSaveInstanceState() と onRestoreInstanceState() を使います。
  1. @Override  
  2. protected void onSaveInstanceState(Bundle outState) {  
  3.     super.onSaveInstanceState(outState);  
  4.     if (mMainFragment != null) {  
  5.         getSupportFragmentManager().putFragment(outState, "main_fragment", mMainFragment);  
  6.     }  
  7. }  
  8.   
  9. @Override  
  10. protected void onRestoreInstanceState(Bundle savedInstanceState) {  
  11.     super.onRestoreInstanceState(savedInstanceState);  
  12.     if (mMainFragment == null) {  
  13.         mMainFragment = (MainFragment) getSupportFragmentManager().getFragment(savedInstanceState, "main_fragment");  
  14.     }  
  15. }  
実際に Fragment のインスタンスがこの処理で永続化されるわけではなく、画面回転後に以前のものと対応する Fragment を見つけてくるという処理です。


0 件のコメント:

コメントを投稿