समस्या का सारांश
नोट: इस उत्तर में मैं संदर्भ FragmentPagerAdapter
और इसके स्रोत कोड पर जा रहा हूं । लेकिन सामान्य समाधान भी लागू होना चाहिए FragmentStatePagerAdapter
।
यदि आप इसे पढ़ रहे हैं, तो आप शायद पहले से ही जानते हैं कि FragmentPagerAdapter
/ आपके FragmentStatePagerAdapter
लिए बनाने के Fragments
लिए है ViewPager
, लेकिन गतिविधि मनोरंजन पर (चाहे डिवाइस रोटेशन से या सिस्टम आपके मेमोरी को पुनः प्राप्त करने के लिए ऐप को मार रहा हो) ये Fragments
फिर से नहीं बनाए जाएंगे, बल्कि उनके बजाय उदाहरणों से पुनः प्राप्तFragmentManager
। अब कहो कि उन पर काम करने के Activity
लिए आपको इनका संदर्भ प्राप्त करने की आवश्यकता है Fragments
। आपके पास इन के लिए id
या नहीं है क्योंकि उन्हें आंतरिक रूप से सेट करें । तो समस्या यह है कि उस जानकारी के बिना उनके लिए एक संदर्भ कैसे प्राप्त किया जाए ...tag
Fragments
FragmentPagerAdapter
वर्तमान समाधान के साथ समस्या: आंतरिक कोड पर निर्भर
बहुत सारे समाधान मैंने इस पर देखे हैं और इसी तरह के प्रश्न मौजूदा बनाएFragment
गए कॉल के संदर्भ को प्राप्त करने FragmentManager.findFragmentByTag()
और आंतरिक रूप से बनाए गए टैग की"android:switcher:" + viewId + ":" + id
नकल करने पर निर्भर करते हैं :। इसके साथ समस्या यह है कि आप आंतरिक स्रोत कोड पर भरोसा कर रहे हैं, जैसा कि हम सभी जानते हैं कि हमेशा के लिए एक ही रहने की गारंटी नहीं है। Google में एंड्रॉइड इंजीनियर आसानी से 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
और इसके बजाय उन्हें पुनर्प्राप्त करने के लिए उचित एपीआई का उपयोग करती है। इस तरह से भले ही 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...
}