Sorunun özeti
Not: Bu cevapta FragmentPagerAdapter
kaynak koduna atıfta bulunacağım. Ancak genel çözüm için de geçerli olmalıdır FragmentStatePagerAdapter
.
Bunu okuyorsanız, muhtemelen sizin için yaratmanın FragmentPagerAdapter
/ FragmentStatePagerAdapter
yaratmanın amaçlandığını zaten biliyorsunuzdur , ancak Aktivite rekreasyonunda (ister cihaz rotasyonundan ister Uygulamanızı yeniden hafızaya almak için uygulamanızı öldüren sistemden) bunlar tekrar oluşturulmayacak, bunun yerine örneklerinden . Şimdi, üzerinde çalışmak için bunlara referans almanız gerektiğini söyleyin. Oluşturulanlar için bir veya yok, çünkü onları dahili olarak ayarlayınFragments
ViewPager
Fragments
FragmentManager
Activity
Fragments
id
tag
Fragments
FragmentPagerAdapter
. Yani sorun, bu bilgi olmadan onlara nasıl referans alınacağı ...
Mevcut çözümlerle ilgili sorun: dahili koda güvenmek
Bu ve benzeri sorular üzerinde gördüğüm çözümlerin bir sürü mevcut bir başvuru alma güveniyor Fragment
arayarak FragmentManager.findFragmentByTag()
ve taklit içten oluşturulan etiketi:"android:switcher:" + viewId + ":" + id
. Bununla ilgili sorun, hepimizin bildiği gibi sonsuza kadar aynı kalacağının garantisi olmayan dahili kaynak koduna güvenmenizdir. Google'daki Android mühendisleri, tag
kodunuzu bozacak yapıyı değiştirmeye kolayca karar verebilir ve sizi mevcut bir referans bulamazsınız.Fragments
.
İçeriye güvenmeden alternatif çözüm tag
İşte bir başvuru nasıl basit bir örnek Fragments
tarafından döndürülen FragmentPagerAdapter
iç güvenmek etmediğini tags
üzerinde kümesi Fragments
. Anahtar geçersiz kılma etmektir instantiateItem()
orada referansları ve kaydetme yerine içinde 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();
}
}
}
ya sen çalışmak isterseniz tags
sınıf üyesi değişkenleri yerine / atıflar Fragments
size de kapabilirsiniz tags
tarafından seti FragmentPagerAdapter
aynı şekilde: NOT: Bu uygulanmaz FragmentStatePagerAdapter
ayarlandıktan olmadığından tags
it'i oluştururken 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;
}
Bu yöntemin dahili tag
seti taklit etmeye dayanmadığını FragmentPagerAdapter
ve bunun yerine bunları almak için uygun API'leri kullandığını unutmayın. Bu şekilde tag
ilerideki sürümlerdeki değişiklikler bile SupportLibrary
güvende olacaksınız.
Unutma , aramalarınızdan tasarımına bağlı olduğunu Activity
, Fragments
sen olabilir çalışma çalışıyorsanız veya sahip böyle yaparak bunun için hesaba, henüz olmayabilir null
referanslarını kullanmadan önce çekleri.
Ayrıca, bunun yerine çalışıyorsanız FragmentStatePagerAdapter
, o zaman kendinize sıkı referanslar tutmak istemezsiniz Fragments
çünkü bunların çoğuna sahip olabilirsiniz ve sert referanslar gereksiz yere hafızada tutabilir. Bunun yerine Fragment
referansları WeakReference
standart olanlar yerine değişkenlere kaydedin . Bunun gibi:
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...
}