54

मेरे पास एक टुकड़ा है जिसमें व्यूपेजर है। ViewPager एक एडाप्टर से जुड़ा हुआ है जिसमें टुकड़ों का एक सेट होता है।एक टुकड़े के भीतर खंड खंडदर्शी प्रदर्शित करें

पैरेंट खंड को लोड करने पर, मुझे संदेश के साथ IllegalStateException से मुलाकात की गई है: java.lang.IllegalStateException: Recursive entry to executePendingTransactions

कुछ शोध मुझे निष्कर्ष यह है कि प्रणाली एक और टुकड़ा के भीतर असमर्थ प्रदर्शन टुकड़े है के लिए प्रेरित किया, लेकिन वहाँ कुछ संकेत हैं कि यह वास्तव में एक ViewPager (A bug in ViewPager using it with other fragment) के उपयोग के साथ ऐसा करना संभव है हो रहा है।

असल में, अगर मैं अपने माता-पिता खंड में एक बटन जोड़ता हूं जो दबाए जाने पर मेरे व्यूपेजर पर mPager.setAdapter(mAdapter) पर कॉल करता है, तो ViewPager सफलतापूर्वक लोड हो जाता है। यह आदर्श नहीं है।

मुद्दा तब खंड खंडन से संबंधित होना चाहिए। इसलिए मेरा सवाल यह है: क्या किसी और को इस मुद्दे के आसपास एक रास्ता मिला है, और यदि हां, तो कैसे?

क्या विखंडन लेनदेन के बाद तक ViewPager पर एडाप्टर सेटिंग्स को देरी करने का कोई तरीका है?

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

    mView = inflater.inflate(R.layout.team_card_master, container, false); 
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); 

    final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); 
    button.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      mViewPager.setAdapter(mAdapter); 
      button.setVisibility(View.GONE); 
     } 
    }); 

    mAdapter = new ViewPagerAdapter(getFragmentManager()); 
//  mViewPager.setAdapter(mAdapter); 

    return mView; 
} 

और अनुकूलक:

public class ViewPagerAdapter extends FragmentPagerAdapter { 
    public ViewPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public int getCount() { 
     if (mCursor == null) return 0; 
     else return mCursor.getCount(); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     Bundle b = createBundle(position, mCursor); 
     return TeamCardFragment.newInstance(b); 
    } 
} 
+8

एंड्रॉइड सपोर्ट लाइब्रेरी के संशोधन 11 में टुकड़े घोंसले की क्षमता को जोड़ा गया है। फ्रैगमेंट क्लास में अब "getChildFragmentManager" विधि है। मैंने इसी तरह की एक साधारण परियोजना बनाई जो https: // github पर पाया जा सकता है।com/marsucsb/नेस्टेड-टुकड़े –

+0

http://stackoverflow.com/q/18097567/1503130 क्या आप इस – Prateek

उत्तर

60

उपयोग viewPager के लिए एडाप्टर सेट करने के लिए AsyncTask

यहाँ मेरी माता पिता टुकड़ा कोड है। इससे मेरा काम बनता है। AsyncTask मूल खंड को पूरा करने के लिए यह संक्रमण है। और फिर हम रिकर्सन से बचने के लिए मूल रूप से दृश्य पेजर के साथ आगे बढ़ते हैं।

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

    mView = inflater.inflate(R.layout.team_card_master, container, false); 
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); 

    final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); 
    button.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      mViewPager.setAdapter(mAdapter); 
      button.setVisibility(View.GONE); 
     } 
    }); 

    mAdapter = new ViewPagerAdapter(getFragmentManager()); 
    new setAdapterTask().execute(); 

    return mView; 
} 

private class setAdapterTask extends AsyncTask<Void,Void,Void>{ 
     protected Void doInBackground(Void... params) { 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void result) { 
        mViewPager.setAdapter(mAdapter); 
     } 
} 
+0

के साथ मेरी मदद कर सकते हैं ठीक है- इतना सही नहीं है। मुझे एक मुद्दा था जहां दृश्य को फिर से बनाया गया था जब दर्शक में विचार काले थे - क्योंकि अंदर के टुकड़ों का पुन: उपयोग किया जाता है। मैंने इस कोड को टुकड़े के टुकड़े में रखने के साथ हल किया है: – Jords

+1

int स्थिति = 0; (टैबइन्फो जानकारी: mTabsAdapter.mTabs) { स्ट्रिंग टैग = FragmentPagerAdapter.makeFragmentName (mViewPager.getId(), स्थिति); टुकड़ा टुकड़ा; FragmentTransaction ft = getSupportFragmentManager()। StartTransaction(); अगर ((खंड = getFragmentManager()। FindFragmentByTag (टैग))! = शून्य) { ft.remove (खंड); } ft.commit(); स्थिति ++; } ... यह बहुत भयानक है: ओ – Jords

+0

आपका समाधान ठीक काम कर रहा है लेकिन जब मैं बैक बटन दबाता हूं तो फिर खंड को संलग्न करता हूं केवल पहले दो टुकड़े दिखाई देते हैं और तीसरे टुकड़े की सामग्री अदृश्य होती है। कृपया –

37

Jords, मुझे लगता है कि आप FragmentStatePagerAdapter बजाय FragmentPageAdapter उपयोग कर सकते हैं। यह आपके लिए टुकड़े हटा देगा।

पीएस। टिप्पणी के बजाय उत्तर का उपयोग करने के लिए खेद है लेकिन मेरी प्रतिष्ठा बहुत कम है।

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    mHandler.post(new Runnable() { 
     @Override 
     public void run() { 
      mViewPager.setAdapter(mAdapter);  
     } 
    });   
} 
19

मैं मूल टुकड़ा लेनदेन के बाहर अनुकूलक सेट करने के लिए Handler.post() इस्तेमाल किया। मेरे पास Fragment था जिसे Fragments के ViewPager होस्ट करने की आवश्यकता थी। जब मैंने अपने ViewPagerFragment के शीर्ष पर Fragment स्टैक्ड किया, और फिर वापस हिट किया, तो मुझे IllegalStateException मिल जाएगा। लॉग की जांच करने के बाद (जब एक नया Fragment ढेर करते हैं), मैंने पाया कि मेरा ViewPagerFragment अपने जीवन चक्र के तरीकों को रोकने और नष्ट करने के लिए जाएगा, हालांकि में FragmentsonResume में रहेंगे। मुझे एहसास हुआ कि FragmentsFragmentManagerViewPagerFragment के लिए FragmentManagerActivity के लिए द्वारा प्रबंधित किया जाना चाहिए।

मैं उस समय समझता हूं, ऊपर दिए गए उत्तरों Fragments की सीमाओं को प्राप्त करने के लिए थे Fragments। हालांकि, अब नवीनतम समर्थन लाइब्रेरी को Fragment घोंसले के लिए समर्थन है, अब आपको अपने ViewPager के लिए एडाप्टर सेट करने के आसपास हैक करने की आवश्यकता नहीं है, और आपको getChildFragmentManager() पास करने की आवश्यकता है। यह अब तक मेरे लिए पूरी तरह से काम कर रहा है।

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

    mView = inflater.inflate(R.layout.team_card_master, container, false); 
    mViewPager = (ViewPager) mView.findViewById(R.id.team_card_master_view_pager); 

    mAdapter = new ViewPagerAdapter(getChildFragmentManager()); 
    mViewPager.setAdapter(mAdapter); 

    return mView; 
} 
+1

वह mHandler कहां से आ रहा है? –

+0

यह एक सदस्य होना चाहिए और आप इसे 'ऑनक्रेट() ':' mHandler = new हैंडलर(); ' – inazaruk

+2

में तत्काल कर सकते हैं क्या यह दृष्टिकोण टुकड़ों के बीच स्विचिंग के साथ किसी भी समस्या का कारण बनता है? मुझे वर्तमान में कोई समस्या है यदि मैं एक अलग टुकड़े पर जाता हूं तो फिर व्यूपेजर युक्त एक पर वापस लौटें। यह सामग्री नहीं दिखा रहा है और यह ठीक से स्क्रॉल नहीं कर रहा है। –

22

मैं सिर्फ यह एक ही समस्या में पड़ गए:

+0

हाल के एंड्रॉइड संस्करणों के लिए यह स्वीकार्य उत्तर होना चाहिए। – Haspemulator

+0

getChildFragmentManager खंड के लिए है मैं गतिविधि के अंदर समस्या को कैसे हल कर सकता हूं? –

+0

@ मिलाद यदि 'गतिविधि '' Fragments' के' ViewPager' का प्रबंधन कर रहा है, तो 'गतिविधि' के 'FragmentManager' ('getFragmentManager()') को' एडाप्टर 'पर पास करें –

0

मैं जब ViewCreated पर में TabIndicator पर viewPager एडाप्टर प्रारंभ करने की कोशिश कर इस समस्या का सामना करना पड़ा है। ऑनलाइन इसके बारे में पढ़ने के बाद मुझे एहसास हुआ कि यह सिर्फ इसलिए हो सकता है क्योंकि विभाजन अभी तक गतिविधि में नहीं जोड़ा गया था। इसलिए मैंने प्रारंभिक कोड को खंड के ऑनस्टार्ट() में स्थानांतरित कर दिया, इससे आपकी समस्या हल होनी चाहिए। लेकिन मेरे लिए नहीं, मुझे अभी भी एक ही समस्या मिल रही थी।

लेकिन वह था, क्योंकि मेरी कोड में मैं, बाईपास स्पष्ट रूप से लंबित कार्य के सामान्य async निष्पादन executePendingTransactions करने के लिए कॉल() कोशिश कर रहा था अवरोधित करने के बाद कि सब कुछ अच्छी तरह से

0

काम किया माता-पिता टुकड़ा लोड हो रहा है पर, मैंने संदेश के साथ एक IllegalStateException के साथ मुलाकात की: java.lang.IleglegalStateException: executePendingTransactions निष्पादित करने के लिए रिकर्सिव प्रविष्टि।

कुछ शोध ने मुझे निष्कर्ष निकाला है कि सिस्टम किसी अन्य टुकड़े के भीतर टुकड़े प्रदर्शित करने में असमर्थ है, फिर भी ऐसा लगता है कि ऐसा कुछ संकेत है कि व्यूपेजर के उपयोग के साथ यह वास्तव में करना संभव है (ViewPager में एक बग यह अन्य टुकड़े के साथ)।

स्पष्ट रूप से ViewPager के लिए आईडी सेट करें।

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     mView = inflater.inflate(R.layout.team_card_master, container, false); 
     mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); 
     mViewPager.setId(100); 

     final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); 
     button.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      mViewPager.setAdapter(mAdapter); 
      button.setVisibility(View.GONE); 
     } 
     }); 
     mAdapter = new ViewPagerAdapter(getFragmentManager()); 
     mViewPager.setAdapter(mAdapter); 

     return mView; 
    } 

आप एक जादुई संख्या 100.

<resources> 
    <item name="Id_For_ViewPager" type="id"/> 
</resources> 

और setId (R.Id_For_ViewPager) के बजाय अपने xml संसाधनों में आईडी का उपयोग कर सकते हैं।

अधिक जानकारी के लिए FragmentManager.java स्रोत देखें।

https://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/app/FragmentManager.java#L900

या इस पृष्ठ को देखें (जापानी)। मूल विचार उससे है, असल में, मुझे नहीं। http://y-anz-m.blogspot.jp/2012/04/androidfragment-viewpager-id.html

0

थॉमस Amssler द्वारा इस शानदार पोस्ट का उपयोग करना: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html

iv'e एक एडाप्टर के टुकड़े के सभी प्रकार बनाने के लिए इस्तेमाल किया जा सकता है बनाया। एडाप्टर ही इस तरह दिखेगा:

public abstract class EmbeddedAdapter extends FragmentStatePagerAdapter { 

private SparseArray<WeakReference<Fragment>> mPageReferenceMap = new SparseArray<WeakReference<Fragment>>(); 
private ArrayList<String> mTabTitles; 

public abstract Fragment initFragment(int position); 

public EmbeddedAdapter(FragmentManager fm, ArrayList<String> tabTitles) { 
    super(fm); 
    mTabTitles = tabTitles; 
} 

@Override 
public Object instantiateItem(ViewGroup viewGroup, int position) { 
    mPageReferenceMap.put(Integer.valueOf(position), new WeakReference<Fragment>(initFragment(position))); 
    return super.instantiateItem(viewGroup, position); 
} 

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

@Override 
public CharSequence getPageTitle(int position) { 
    return mTabTitles.get(position); 
} 

@Override 
public Fragment getItem(int pos) { 
    return getFragment(pos); 
} 

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

public Fragment getFragment(int key) { 

    WeakReference<Fragment> weakReference = mPageReferenceMap.get(key); 

    if (null != weakReference) { 

     return (Fragment) weakReference.get(); 

    } else { 
     return null; 
    } 
} 

@Override 
public int getItemPosition(Object object) { 
    return POSITION_NONE; 
} 

}

एडाप्टर का उपयोग करने के लिए आप निम्न कार्य करना होगा:

private void setAdapter() { 

    if(mAdapter == null) mAdapter = new EmbeddedAdapter(getActivity().getSupportFragmentManager(), mTabTitles) { 

     @Override 
     public Fragment initFragment(int position) { 

      Fragment fragment; 

      if(position == 0){ 

       // A start fragment perhaps? 
       fragment = StartFragment.newInstance(mBlocks); 

      }else{ 

       // Some other fragment 
       fragment = PageFragment.newInstance(mCategories.get((position))); 
      } 
      return fragment; 
     } 
    }; 

    // Have to set the adapter in a handler 
    Handler handler = new Handler(); 
    handler.post(new Runnable() { 

     @Override 
     public void run() { 

      mViewPager.setVisibility(View.VISIBLE); 
      mPagerTabStrip.setVisibility(View.VISIBLE); 
      mAdapter.notifyDataSetChanged(); 
     } 
    }); 
} 

ध्यान दें कि सभी टुकड़े का उपयोग करें:

setRetainInstance(true); 
संबंधित मुद्दे