問題の要約
注:この回答ではFragmentPagerAdapter
、そのソースコードと参照します。ただし、一般的な解決策はにも適用されFragmentStatePagerAdapter
ます。
あなたがこれを読んでいる場合、あなたはおそらく既にそれは知っているFragmentPagerAdapter
/ FragmentStatePagerAdapter
作成するためのものですFragments
、あなたのためにViewPager
、これらは(デバイスの回転やシステムからメモリを取り戻すにアプリを殺すかどうか)が、活動レクリエーション時にFragments
再び作成され、代わりに自分のことはありませんから取得したインスタンスFragmentManager
。ここで、それらに取り組むActivity
ためにこれらFragments
への参照を取得する必要があると言います。内部で設定されているため、これらのforid
またはtag
forは作成されていません。したがって、問題はその情報なしでそれらへの参照を取得する方法です...Fragments
FragmentPagerAdapter
現在のソリューションの問題:内部コードに依存
これと同様の質問で私が見たソリューションの多くは、内部で作成されたタグをFragment
呼び出しFragmentManager.findFragmentByTag()
て模倣することにより、既存のものへの参照を取得することに依存しています。これの問題は、内部ソースコードに依存していることです。これは、ご存じのとおり、永久に同じままであることが保証されているわけではありません。GoogleのAndroidエンジニアは、既存のへの参照を見つけることができずにコードが壊れる構造を変更することを簡単に決定できます。"android:switcher:" + viewId + ":" + id
tag
Fragments
内部に依存しない代替ソリューション tag
これは、の内部セットに依存しないFragments
、によって返されるへの参照を取得する方法の簡単な例です。キーはオーバーライドすることですFragmentPagerAdapter
tags
Fragments
instantiateItem()
代わりに参照して保存することgetItem()
です。
public class SomeActivity extends Activity {
private FragmentA m1stFragment;
private FragmentB m2ndFragment;
// other code in your Activity...
private class CustomPagerAdapter extends FragmentPagerAdapter {
// other code in your custom FragmentPagerAdapter...
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// Do NOT try to save references to the Fragments in getItem(),
// because getItem() is not always called. If the Fragment
// was already created then it will be retrieved from the FragmentManger
// and not here (i.e. getItem() won't be called again).
switch (position) {
case 0:
return new FragmentA();
case 1:
return new FragmentB();
default:
// This should never happen. Always account for each position above
return null;
}
}
// Here we can finally safely save a reference to the created
// Fragment, no matter where it came from (either getItem() or
// FragmentManger). Simply save the returned Fragment from
// super.instantiateItem() into an appropriate reference depending
// on the ViewPager position.
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
// save the appropriate reference depending on position
switch (position) {
case 0:
m1stFragment = (FragmentA) createdFragment;
break;
case 1:
m2ndFragment = (FragmentB) createdFragment;
break;
}
return createdFragment;
}
}
public void someMethod() {
// do work on the referenced Fragments, but first check if they
// even exist yet, otherwise you'll get an NPE.
if (m1stFragment != null) {
// m1stFragment.doWork();
}
if (m2ndFragment != null) {
// m2ndFragment.doSomeWorkToo();
}
}
}
またはあなたが作業する場合はtags
代わりに、クラスのメンバ変数の/への参照は、Fragments
あなたもつかむことができますtags
ことでセットをFragmentPagerAdapter
同じように:注:これはには適用されませんFragmentStatePagerAdapter
、それが設定されていませんので、tags
そのを作成するときFragments
。
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
// get the tags set by FragmentPagerAdapter
switch (position) {
case 0:
String firstTag = createdFragment.getTag();
break;
case 1:
String secondTag = createdFragment.getTag();
break;
}
// ... save the tags somewhere so you can reference them later
return createdFragment;
}
このメソッドは内部の模倣に依存しないことに注意してください tag
セットのFragmentPagerAdapter
適切なAPIを使用してそれらを取得することに注意してください。このようにしてもtag
、将来のバージョンでの変更はSupportLibrary
安全です。
忘れないで、あなたのデザインに応じていることをActivity
、Fragments
あなたは日に仕事にしようとしているか、あなたが持っているそうで、そのためにアカウントに、まだ存在しないかもしれないnull
、あなたの参照を使用する前にチェックを。
また、代わりにを使用している場合はFragmentStatePagerAdapter
、ハード参照をFragments
多く保持している可能性があり、ハード参照がメモリに不必要に保持するため、ハード参照を保持したくない場合があります。代わりに、Fragment
参照WeakReference
を標準の変数ではなく変数に保存します。このような:
WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment);
// ...and access them like so
Fragment firstFragment = m1stFragment.get();
if (firstFragment != null) {
// reference hasn't been cleared yet; do work...
}