2012-05-18 12 views
16

मैं this example का उपयोग कर FragmentStatePagerAdapter के साथ काम कर रहा हूं।एंड्रॉइड FragmentStatePagerAdapter

MyAdapter वर्ग के रूप में कार्यान्वित किया जाता है इस प्रकार है:

public static class MyAdapter extends FragmentStatePagerAdapter { 
     public MyAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public int getCount() { 
      return NUM_ITEMS; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      return ArrayListFragment.newInstance(position); 
     } 
    } 

ListFragment वर्ग एक नया उदाहरण बनाने के लिए निम्न विधि में शामिल हैं:

/** 
    * Create a new instance of CountingFragment, providing "num" 
    * as an argument. 
    */ 
    static ArrayListFragment newInstance(int num) { 
     ArrayListFragment f = new ArrayListFragment(); 

     // Supply num input as an argument. 
     Bundle args = new Bundle(); 
     args.putInt("num", num); 
     f.setArguments(args); 

     return f; 
    } 

जब मैं में एक नया टुकड़ा राज्य पेजर एडाप्टर बनाने मेरी गतिविधि, getItem कहा जाता है, जो बदले में ListFragment क्लास में newInstance विधि को कॉल करता है। यह बहुत अच्छा है जब मैं एक नया टुकड़ा बनाना चाहता हूं।

लेकिन यह मेरे लिए स्पष्ट कैसे संशोधित करने के लिए नहीं है getItem (यदि भी आवश्यक) टुकड़ा वस्तु पाने के लिए जब यह पहले से ही, से उदाहरण के लिए, पृष्ठ 1. करने के लिए पेज 2 मैं चाहता और उपयोगकर्ता पृष्ठों मौजूद है मेरी उस मौजूदा, पहले बनाए गए टुकड़े को पुनः प्राप्त करने के लिए गतिविधि ताकि वह एक आंतरिक वर्ग AsyncMethod चला सके, जो खंड वर्ग में रहता है।

+2

'GetItem()' एक अजीब नाम है, यह कार्यक्षमता आप की सोच रहे हैं प्रदान नहीं करता है। कृपया एक ही विषय पर अपना खुद का प्रश्न देखें: http://stackoverflow.com/questions/10574114/referencing-fragments-inside-viewpager –

+0

यह बहुत उपयोगी लगता है। लेकिन मैं एक सूचीफ्रेम का उपयोग कर रहा हूं और उम्मीद कर रहा था कि मैं अपना खुद का प्राप्त करने के बजाय getSelectedItemPosition का उपयोग कर रहा हूं। मुझे इसके साथ कुछ और खेलना होगा और देखें कि क्या मैं यह समझ सकता हूं कि इसे कैसे किया जाए। – mraviator

+0

मैंने सूचीफ्रेमेंट का भी उपयोग किया, लेकिन यह बस इस तरह से काम नहीं करता है। हालांकि अगर आपको कुछ मिल जाए, तो मुझे –

उत्तर

3

मैंने आपके पास जो कुछ भी है उसके समान कुछ लागू किया है। मैं तो जैसे FragmentPagerAdapter वर्ग बढ़ाया:

public class ContactsFragmentPagerAdapter extends FragmentPagerAdapter { 
    ActionBar mActionBar; 
    private List<Fragment> mFragments; 

    public ContactsFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) { 
     super(fm); 
     mFragments = fragments; 
    } 

    @Override 
    public int getCount() { 
     return mFragments.size(); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return mFragments.get(position); 
    } 

    public void setActionBar(ActionBar bar) { 
     mActionBar = bar; 
    } 
} 

सूचना मैं निर्माता के लिए एक तर्क को शामिल किया है Fragment की List वस्तुओं में पारित करने के लिए। इस प्रकार getItem() इस वर्ग की विधि किसी भी कक्षा को वापस कर सकती है जो Fragment या इसके किसी भी उप-वर्ग को बढ़ाती है और न केवल एक विशिष्ट वर्ग ArrayListFragment आपके द्वारा की गई है।

Activity मैं कहाँ का दृष्टांत FragmentPagerAdapter की मेरी उपवर्ग मैं Fragment वस्तुओं की सूची में पारित किया है में: FragmentPagerAdapter

public final class ContactManager extends Activity { 
    private ContactsFragmentPagerAdapter mAdapter; 
    private ViewPager mPager; 
    public ActionBar mActionBar; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.contact_manager); 

     List<Fragment> fragments = new Vector<Fragment>(); 
     fragments.add(Fragment.instantiate(this, ContactsListFragment.class.getName())); 
     fragments.add(Fragment.instantiate(this, GroupsListFragment.class.getName())); 
     mAdapter = new ContactsFragmentPagerAdapter(this.getFragmentManager(), fragments); 

     mPager = (ViewPager) findViewById(R.id.pager); 
     mPager.setAdapter(mAdapter); 

     mPager.setOnPageChangeListener(new OnPageChangeListener() { 
      @Override 
      public void onPageScrollStateChanged(int arg0) {} 

      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) {} 

      @Override 
      public void onPageSelected(int arg0) { 
       mActionBar.getTabAt(arg0).select(); 
      } 
     }); 

    } 

} 

क्लास को दर्शाता है चर "टुकड़े" पहुँचने से, आप कर सकते हैं पहले बनाए गए Fragment तक पहुंचें ताकि आप Fragment के विधियों को चला सकें।

+13

हालांकि यह एक ही टुकड़ा संलग्न कर सकता है, यह अच्छा होगा अगर कोई ऐसा समाधान था जो सभी टुकड़ों को हमेशा 'FragmentStatePagerAdapter' के साथ काम करने के लिए तत्काल नहीं रखता था, क्योंकि यह वास्तव में उस एडाप्टर का पूरा बिंदु है। – blahdiblah

+2

@blahdiblah मेरे उत्तर पर एक नज़र डालें। – imiric

4
public class MyPagerAdapter extends FragmentStatePagerAdapter { 
    final Context m_context; 
    final WeakReference<Fragment>[] m_fragments; 

    public DetailPagerAdapter(FragmentManager fm) { 
     super(fm); 
     m_context = ... 
       m_fragments = new WeakReference[enter size here]; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     final Fragment fragment = instantiate your fragment; 
     m_fragments[position] = new WeakReference<Fragment>(fragment); 
     return fragment; 
    } 

    @Override 
    public int getCount() { 
     return ... 
    } 

    public Fragment getFragment(final int position) { 
     return m_fragments[position] == null ? null : 
      m_fragments[position].get(); 
    } 
} 
+0

मेरे लिए यह सबसे सस्ता तरीका है, धन्यवाद – j2emanue

0

FragmentPagerAdapter को संशोधित करने की आवश्यकता नहीं है, क्योंकि खंडों को FragmentManager द्वारा कैश किया जाता है। तो आपको इसके अंदर खोजने की ज़रूरत है। पेजर एडाप्टर स्थिति द्वारा खंड को खोजने के लिए इस फ़ंक्शन का उपयोग करें। v4 समर्थन एपीआई के लिए

public Fragment findFragmentByPosition(int position) { 
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter(); 
    return getSupportFragmentManager().findFragmentByTag(
      "android:switcher:" + getViewPager().getId() + ":" 
        + fragmentPagerAdapter.getItemId(position)); 
} 

नमूना कोड।

+0

क्या यह समर्थन एपीआई के लिए नमूना कोड में शामिल है या आपने इसे समर्थन एपीआई के लिए स्वयं लिखा है? (यदि यह वहां है, तो मैं कम से कम 'सेमी-आधिकारिक' होगा) – Patrick

+0

मैं एंड्रॉइड एपीआई के स्रोत कोड के आधार पर इसे स्वयं लिखता हूं, और मेरा मतलब है "वी 4 के लिए नमूना कोड" क्योंकि यह कोड "getSupportFragmentManager" का उपयोग करता है "यह तब उपलब्ध होता है जब आप समर्थन लाइब्रेरी का उपयोग करते हैं, यदि आप 'समर्थन लाइब्रेरी' का उपयोग नहीं करते हैं, तो आपको" getFragmentManager "के लिए कम से कम" getSupportFragmentManager "को बदलने की आवश्यकता होगी। एफवाईआई: http://developer.android.com/tools/extras/support-library.html –

+1

Thx। मुझे आशा थी कि उन्होंने इसे किसी भी तरह से आधिकारिक बनाया होगा। यह भविष्य में तोड़ सकता है ... आह ठीक है, लेकिन धन्यवाद! – Patrick

37

मुझे लगता है कि समाधान प्रदान किए गए उत्तरों से कहीं अधिक सरल है।

आप source of FragmentStatePagerAdapter.instantiateItem() पर एक नज़र डालें, तो आप देखेंगे कि instantiateItem() आप के लिए यह तर्क संभालती है, और इस तरह getItem() अपने क्रियान्वयन की हमेशा एक नया उदाहरण लौटना चाहिए।

तो आदेश एक मौजूदा टुकड़ा वापस जाने के लिए में, बस (यह मानते हुए आप ViewPager से फोन कर रहे हैं) है:

Fragment f = (Fragment) getAdapter().instantiateItem(this, getCurrentItem()); 
+4

सबसे अच्छा जवाब नीचे छिपा रहा था !!! सार्वजनिक शून्य पर पेजस्क्रोल किया गया (int i, float v, int i2) { टुकड़ा टुकड़ा = (टुकड़ा) imagePagerAdapter.instantiateItem (mImageViewPager, i); –

+2

केवल स्रोत को देखने के बाद मुझे समस्या का तर्क पता चला। और देखें कि यह पृष्ठ पर एकमात्र तार्किक उत्तर है। आपका बहुत बहुत धन्यवाद। –

+1

ग्रेट उत्तर, धन्यवाद। –

5

जबकि @ imiric के समाधान बहुत संक्षिप्त है, यह अभी भी मुझे परेशान है कि यह के ज्ञान की आवश्यकता कक्षा के कार्यान्वयन। मेरे समाधान अपने एडाप्टर के लिए निम्न है, जो एक FragmentStatePagerAdapter संभवतः टुकड़े को नष्ट करने के साथ अच्छी तरह से व्यवहार करना चाहिए जोड़ने शामिल है:

private SparseArray<WeakReference<Fragment>> mFragments = new SparseArray<>(); 

    @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
     Fragment f = (Fragment) super.instantiateItem(container, position); 
     mFragments.put(position, new WeakReference<>(f)); // Remember what fragment was in position 
     return f; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     super.destroyItem(container, position, object); 
     mFragments.remove(position); 
    } 

    public Fragment getFragment(int position) { 
     WeakReference<Fragment> ref = mFragments.get(position); 
     Fragment f = ref != null ? ref.get() : null; 
     if (f == null) { 
      Log.d(TAG, "fragment for " + position + " is null!"); 
     } 
     return f; 
    } 
+3

आपको टुकड़ों के संदर्भ नहीं रखना चाहिए क्योंकि उन्हें किसी भी समय नष्ट और पुनर्निर्मित किया जा सकता है। यदि ऐसा होता है तो आपके संदर्भ अमान्य होंगे और टुकड़े एकत्रित कचरा नहीं हो सकते हैं। – wkarl

+0

दरअसल! वीक रेफरेंस का उपयोग करने के लिए इसे अद्यतन नहीं किया जाएगा हालांकि? – qix

+0

मुझे ऐसा लगता है – wkarl

संबंधित मुद्दे