Android FragmentPagerAdapterとFragmentStatePagerAdapterの違い
5869 ワード
多くのappのメインインタフェースは下部のいくつかのボタンで、それから切り替えをクリックして異なるUIの表示を表示します.これはView pager+fragmentを使って実現することができますが、注意しないと問題があります.
例えばFragmentPagerAdapterを使用する場合、viewpagerがsetCurrentItem(index)を設定している場合.まずindex-1,index+1およびindexに対応するFragmentのviewをロードし、index=0ならfragmentのviewを2つだけロードする.viewpagerがそのインタフェースにスライドすると、そのfragmentのviewがロードされます.例えば、最初から4番目にスライドし、4番目から1番目にスライドします.このとき、4番目のviewは回収されます.viewはnullです.これは、fragmentのviewが繰り返されることを意味します.これまでのFragmentのonDestroyView()ライフサイクルメソッドが実行されるため、viewは回収されます.もしあなたがまたviewpagerのスライドリスニングをしてviewを通じてどんな業務をするのはN ullPointerExceptionの異常を招きやすいならば、私の前のプロジェクトは出会ったことがあって、繰り返しviewをロードする問題はどのように解決しますか?
第一に、viewpagerのキャッシュをfragmentの個数に設定します.
viewpager.setOffscreenPageLimit(fragmentの個数);
これらの現象は、ロゴを打つことで自分で分析することができます.
FragmentStatePagerAdapaterを使用している場合、viewpagerがスライドするとfragmentがメモリから消去されます.これはソースコードから分析できます.
最後の行はFragmentを削除し、FragmentPagerAdapterのソースコード:
最後の行はFragmentのViewを削除することです.これは両者の大きな違いです.だから、Fragmentが多いときはFragmentStatePagerAdapterを使います.前のFragmentがメモリから削除されるので、メモリを節約します.Fragmentが少ない場合はFragmentPagerAdapterを使います.
もう一つの問題は、動的にFragmentをロードすることです.viewpagerがFragmentを追加または削除することです.これは私のプロジェクトでも遭遇しました.FragmentStatePagerAdapterであれば書き直します.
FragmentPagerAdapterなら書き換えます.
viewpagerはviewpagerのようなfragmentを表示することを覚えています.setCurrentItem(0);これを呼び出さないと、現在削除されているfragmentが表示され、スライドするとそのfragmentが消えることに気づきます.
例えばFragmentPagerAdapterを使用する場合、viewpagerがsetCurrentItem(index)を設定している場合.まずindex-1,index+1およびindexに対応するFragmentのviewをロードし、index=0ならfragmentのviewを2つだけロードする.viewpagerがそのインタフェースにスライドすると、そのfragmentのviewがロードされます.例えば、最初から4番目にスライドし、4番目から1番目にスライドします.このとき、4番目のviewは回収されます.viewはnullです.これは、fragmentのviewが繰り返されることを意味します.これまでのFragmentのonDestroyView()ライフサイクルメソッドが実行されるため、viewは回収されます.もしあなたがまたviewpagerのスライドリスニングをしてviewを通じてどんな業務をするのはN ullPointerExceptionの異常を招きやすいならば、私の前のプロジェクトは出会ったことがあって、繰り返しviewをロードする問題はどのように解決しますか?
第一に、viewpagerのキャッシュをfragmentの個数に設定します.
viewpager.setOffscreenPageLimit(fragmentの個数);
これらの現象は、ロゴを打つことで自分で分析することができます.
FragmentStatePagerAdapaterを使用している場合、viewpagerがスライドするとfragmentがメモリから消去されます.これはソースコードから分析できます.
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView());
while (mSavedState.size() <= position) {
mSavedState.add(null);
}
mSavedState.set(position, fragment.isAdded()
? mFragmentManager.saveFragmentInstanceState(fragment) : null);
mFragments.set(position, null);
mCurTransaction.remove(fragment);
}
最後の行はFragmentを削除し、FragmentPagerAdapterのソースコード:
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
+ " v=" + ((Fragment)object).getView());
mCurTransaction.detach((Fragment)object);
}
最後の行はFragmentのViewを削除することです.これは両者の大きな違いです.だから、Fragmentが多いときはFragmentStatePagerAdapterを使います.前のFragmentがメモリから削除されるので、メモリを節約します.Fragmentが少ない場合はFragmentPagerAdapterを使います.
もう一つの問題は、動的にFragmentをロードすることです.viewpagerがFragmentを追加または削除することです.これは私のプロジェクトでも遭遇しました.FragmentStatePagerAdapterであれば書き直します.
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
FragmentPagerAdapterなら書き換えます.
@Override
public long getItemId(int position) {
int hashCode = mFragment.get(position).hashCode();
return hashCode;
}
viewpagerはviewpagerのようなfragmentを表示することを覚えています.setCurrentItem(0);これを呼び出さないと、現在削除されているfragmentが表示され、スライドするとそのfragmentが消えることに気づきます.