FragmentStatePagerAdapter の欠点
Android Support Library に含まれている FragmentStatePagerAdapter は ViewPager を用いたナビゲーションを実装する上でよく利用されるAPIです。
Fragment に bind したいデータのコレクションを管理させて、 Fragment のインスタンスを作らせるパターンが多いのではないでしょうか。
しかしそんな FragmentStatePagerAdapter ですが、任意の位置の Fragment を削除が難しい問題がありました。
ググると 色々情報が出てきますが、わりとよく見つけられたのが以下のパターン。
public int getItemPosition (Object object) {
return PagerAdapter.POSITION_NONE;
}
確かにこうしておけば、 PagerAdapter#notifyDataSetChanged()
を呼んだときに表示されている Fragment が消えてくれるますが、この方法ではキャッシュされている Fragment が全て破棄されるため Fragment の再生成や描画で割りと処理が重たくなってしまいました。
この問題に対応をするため、今回あらたなライブラリを作りました。
numa08/dynamicfragmentpageradapter
使い方
リポジトリの中のサンプルも見て頂きたいのですが、まずは依存関係を追加します。
compile 'net.numa08:dynamicfragmentpageradapter:0.6'
次にアダプターの実装を行ないます。 v4-support 向けの .support.DynamicFragmentStatePagerAdapter
と、普通の Fragment 向けの DynamicFragmentStatePagerAdapter
があります。
public class HeikeFragmentAdapter extends DynamicFragmentStatePagerAdapter {
// bind したいデータのコレクション
private final List<Heike> heikeList;
public HeikeFragmentAdapter(FragmentManager fm, List<Heike> heikeList) {
super(fm);
this.heikeList = heikeList;
}
// Fragment のインスタンスの生成
// 作られた Fragment は勝手にキャッシュされるので、何も考えずにインスタンスを作ればおk
@Override
public Fragment getItem(int position) {
return HeikeFragment.newInstance(heikeList.get(position));
}
// タブとかと併用する場合はタイトルを返すと良い
@Override
public CharSequence getPageTitle(int position) {
return heikeList.get(position).getName();
}
@Override
public int getCount() {
return heikeList.size();
}
// revemoItem では指定された position のデータを消してあげる
@Override
public void removeItem(int position) {
heikeList.remove(position);
super.removeItem(position);
}
}
Fragment を削除するには、
final int position = mainPager.getCurrentItem();
adapter.removeItem(position);
な感じで removeItem
を呼んで下さい。 notifyDataSetChanged
は不要です。
こういう感じで、真ん中のタブだけを削除するUIの実装が可能になります。
今後の展開
FragmentStatePagerAdapter 相当の物はできたので次は FragmentPagerAdapter 相当のやつを作りますね。