ViewPager सामग्री को फिर से नहीं बनाता है, खाली रहता है / बदल जाता है


86

हम यहाँ ViewPager के साथ एक बहुत ही अजीब मुद्दे से पीड़ित हैं। हम प्रत्येक व्यू पेज पेज पर सूचियों को एम्बेड करते हैं, और सूची डेटा को अपडेट करते समय सूची एडॉप्टर और व्यू पेजर एडेप्टर दोनों पर नोटिफ़ाइडडेसटैंग को ट्रिगर करते हैं।

हम जो निरीक्षण करते हैं, वह यह है कि कभी-कभी, पृष्ठ अपने दृश्य ट्री को अपडेट नहीं करता है, अर्थात खाली रहता है, या कभी-कभी पेजिंग करते समय भी गायब हो जाता है। जब कुछ बार आगे-पीछे करते हैं, तो सामग्री अचानक फिर से दिखाई देगी। ऐसा लगता है जैसे एंड्रॉइड यहां एक व्यू अपडेट को याद कर रहा है। मैंने यह भी देखा कि जब पदानुक्रम दर्शक के साथ डिबगिंग करते हैं, तो एक दृश्य का चयन करना हमेशा इसे फिर से प्रकट करेगा, जाहिर है क्योंकि पदानुक्रम दर्शक चयनित दृश्य को खुद को फिर से तैयार करने के लिए मजबूर करता है।

मैं यह काम भले ही प्रोग्रामिक रूप से नहीं कर पाया; सूची दृश्य या संपूर्ण दृश्य पेजर को अमान्य करने से भी कोई प्रभाव नहीं पड़ा।

यह संगतता-v4_r7 लाइब्रेरी के साथ है। मैंने नवीनतम संशोधन का उपयोग करने की भी कोशिश की, क्योंकि यह पेजर से संबंधित कई मुद्दों को ठीक करने का दावा करता है, लेकिन इसने मामलों को और भी बदतर बना दिया (उदाहरण के लिए, इशारों को तोड़ दिया गया था ताकि यह मुझे कभी-कभी सभी पृष्ठों के माध्यम से पृष्ठ न करने दे।)

क्या कोई और भी इन मुद्दों में चल रहा है, या क्या आपको इस बात का अंदाजा है कि इसका क्या कारण हो सकता है?

जवाबों:


44

हम अंत में एक समाधान खोजने में कामयाब रहे। जाहिर तौर पर हमारे कार्यान्वयन को दो मुद्दों का सामना करना पड़ा:

  1. हमारे एडॉप्टर ने दृश्य को नहीं हटाया destroyItem()
  2. हम विचारों को कैशिंग कर रहे थे ताकि हमें अपने लेआउट को सिर्फ एक बार फुलाया जाए, और, चूंकि हम दृश्य को हटा नहीं destroyItem()रहे थे, हम इसे जोड़ नहीं रहे थे, instantiateItem()लेकिन वर्तमान स्थिति के अनुसार केवल कैश किए गए दृश्य को वापस कर रहे थे।

मैंने ViewPager- के स्रोत कोड में बहुत गहराई से नहीं देखा है और यह बिल्कुल स्पष्ट नहीं है कि आपको ऐसा करना है - लेकिन डॉक्स कहते हैं:

विध्वंस। ()
दिए गए पद के लिए एक पृष्ठ निकालें। एडॉप्टर अपने कंटेनर से दृश्य को हटाने के लिए जिम्मेदार है, हालांकि यह केवल यह सुनिश्चित करना चाहिए कि यह उस समय तक किया जाता है जब वह फिनिशडाउन (व्यूग्रुप) से लौटता है।

तथा:

एक बहुत ही सरल पेजर एडेप्टर पृष्ठ दृश्य का उपयोग करने के लिए खुद को प्रमुख वस्तुओं के रूप में उपयोग करना चुन सकता है, उन्हें निर्माण के बाद तत्काल आईटम (व्यूग्रुप, इंट) से लौटाता है और उन्हें मूल व्यूग्रुप में जोड़ देता है। एक मेलिंग विध्वंस (ViewGroup, int, Object) कार्यान्वयन माता-पिता से दृश्य को हटा देगा ViewGroup और isViewFromObject (देखें, ऑब्जेक्ट) रिटर्न दृश्य == ऑब्जेक्ट; के रूप में लागू किया जा सकता है

तो मेरा निष्कर्ष यह है कि ViewPagerअपने बच्चों को instantiateItem()/ में स्पष्ट रूप से जोड़ने / हटाने के लिए इसके अंतर्निहित एडाप्टर पर निर्भर करता है destroyItem()। यही है, यदि आपका एडेप्टर एक उपवर्ग है PagerAdapter, तो आपके उपवर्ग को इस तर्क को लागू करना होगा।

साइड नोट: के बारे में पता होना इस करता है, तो आप के अंदर सूचियों का उपयोग ViewPager


2
मुझे वही समस्या हो रही है लेकिन FragmentPagerAdapter के साथ, जो मेरे लिए onDestroy को संभालता है। यहां कोई भी दूसरा समाधान काम नहीं करता है।
ग्रेग एनिस

14
समस्या यह भी हो सकती है, कि कोई GetChildFragmentManager के बजाय getFragmentManger का उपयोग कर रहा है
Boy

@ क्या है GetChildFragmentManager?
छेद में आग

1
@ बोय वूवू .... मैंने पूरे दो दिनों तक अपने बाल खींचे थे और यह जानने की कोशिश की कि मुझे अपडेट करने के लिए कुछ भी क्यों नहीं मिला। धन्यवाद! (उन्हें वास्तव में, चाइल्डफ्रैगमेंटमैनगर का उपयोग करने के लिए Google के प्रलेखन पर एक नोटिस देना चाहिए, यह पूरी तरह से ऐसा नहीं है कि आपको एक अलग प्रबंधक की आवश्यकता है)।
user0721090601

@futtetennista मैं यही कर रहा हूँ .. इस मुद्दे का सामना कर रहा हूँ .. क्या आप जाँच कर सकते हैं .. stackoverflow.com/questions/61727835/…
AskQ

55

यदि ViewPagerएक के साथ एक टुकड़ा के अंदर सेट किया गया है FragmentPagerAdapter, तो अपने इनिशियलाइज़ करने के लिए पैरामीटर के getChildFragmentManager()बजाय का उपयोग getSupportFragmentManager()करें FragmentPagerAdapter

mAdapter = new MyFragmentPagerAdapter(getChildFragmentManager());

के बजाय

mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());

2
अच्छी पकड़, यह एक FragmentPagerAdapter का उपयोग करते समय मेरे मुद्दे को हल करने के लिए लगता है
तोबलीग

1
धन्यवाद - यह काम किया। मैं उस getItem()पर बल देने की कोशिश कर रहा था, FragmentPagerAdapterजिसे एक पुनर्निर्मित फ्रैगमेंट में घोंसला बनाया गया था।
कोसीरा - बार्टोज़ कोसार्की

वाह यह काम आकर्षण की तरह है। मुझे लगता है कि इस मुद्दे को एक टुकड़े में
दर्शकों को फुलाए

इसका समय ऐसा है कि काश हमारे पास मीडियम की तरह क्लैप्स होते, तो मैं आपको इसके लिए 1000+ क्लैप्स दे सकता था। अच्छा काम, यह स्वीकार किया जाना चाहिए जवाब
Codelicious

21

मुझे ठीक वही समस्या थी लेकिन मैंने वास्तव में इसे नष्ट कर दिया था। समस्या फिर भी था मैं नष्ट कर दिया है कि यह उपयोग कर viewPager.removeViewAt(index);के instedviewPager.removeView((View) object);

गलत:

@Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeViewAt(position);
}

सही:

@Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeView((View) object);
}

संकेत के लिए धन्यवाद। काफी समय से इस मुद्दे पर गौर किया जा रहा है।
मोरिट्ज़

2
यह मेरे लिए काम करता है, लेकिन क्या आप जानते हैं कि पहले वाले को समस्या क्यों है?
हन्नाहिट जूल

@HannahMitt removeViewAt बच्चों के ViewPager की वर्तमान सूची में उस विशेष स्थिति में जो कुछ भी दृश्य है, को हटा देगा, और किसी भी क्रम में ViewPager में पृष्ठ जोड़े जा सकते हैं (इसलिए पृष्ठ 0 वास्तव में अनुक्रम 1 या जो भी हो, ViewPager में हो सकता है)। removeView बच्चों की सूची के माध्यम से पुनरावृत्ति करेगा और निर्दिष्ट ऑब्जेक्ट को बिल्कुल हटा देगा।

2
मेरे लिए काम नहीं कर रहा है: टुकड़े करने के लिए दृश्य नहीं डाल सकता। वस्तु यहाँ एक टुकड़ा है।
एफआरके

दृश्य स्थिर होना चाहिए?
कनागलिंगम

10

ViewPager आइटम्स को पुन: उपयोग करने के आसपास चालाक सामान करने की कोशिश करता है, लेकिन जब चीजें बदल गई हों तो आपको नए आइटम पोजिशन वापस करने की आवश्यकता होती है। इसे अपने पेजर एडेप्टर में जोड़ने का प्रयास करें:

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

यह मूल रूप से ViewPager को बताता है कि सब कुछ बदल गया है (और इसे फिर से सब कुछ तत्काल करने के लिए मजबूर करता है)। यही एक चीज है जो मैं अपने सिर के ऊपर से सोच सकता हूं।


1
हां, मैंने इस विकल्प के बारे में इस सूत्र में पढ़ा है: stackoverflow.com/questions/7263291/… - हालाँकि, यह स्लेजहेमर दृष्टिकोण की तरह लगता है। निश्चित रूप से एक और अधिक सुंदर तरीका होना चाहिए? मुझे आश्चर्य है कि क्या यह पेजर पृष्ठों के रूप में सूचियों का उपयोग करने से संबंधित है?
मथायस

यह थोड़ा स्लेजहैमर दृष्टिकोण है, लेकिन आप उससे वापस काम कर सकते हैं। अर्थात विधि से एक सही मान लौटाएँ।
क्रिस बान्स

@ChrisBanes जैसा कि आपने कहा था return POSITION_NONE;, forces it to re-instantiate everythingलेकिन मेरे मामले में मैं सब कुछ फिर से तुरंत नहीं करना चाहता , इसलिए क्या viewमौजूदा सामान को साफ किए बिना निकालना संभव होगा ? कृपया मुझे बताएं
रितेश अदुलकर

आप जीवन के स्वाद हैं
मास्क 8

2

कई समाधानों की कोशिश की लेकिन अप्रत्याशित रूप से viewPager.post()काम किया

 mAdapter = new NewsVPAdapter(getContext(), articles);
    viewPager.post(new Runnable() {
        @Override
        public void run() {
            viewPager.setAdapter(mAdapter);
        }
    });

1
हे भगवान। किसी ने इसे क्यों नहीं उखाड़ा? मैं अजीब व्यवहार मिला जब मैं एक टुकड़ा और दृश्यदर्शी अंदर प्रस्तुत करना ही प्रस्तुत करना नहीं है, और यह इस तरह से वास्तव में समस्या का हल थोड़ा विलंब!
फुगोगुओ

0

एंड्रॉइड सपोर्ट लाइब्रेरी में एक डेमो एक्टिविटी होती है, जिसमें हर पेज पर एक लिस्ट व्यू वाला व्यूपेजर शामिल होता है। आपको संभवतः एक नज़र रखना चाहिए और देखना चाहिए कि यह क्या करता है।

ग्रहण में (Android देव उपकरण r20 के साथ):

  1. चुनते हैं New > Android Sample Project
  2. अपना लक्ष्य API स्तर चुनें (मैं नवीनतम उपलब्ध सुझाव देता हूं)
  3. चुनते हैं Support4Demos
  4. प्रोजेक्ट को राइट-क्लिक करें और चुनें Android Tools > Add Support Library
  5. ऐप को रन करें और चुनें Fragmentऔर फिरPager

इसके लिए कोड है src/com.example.android.supportv4.app/FragmentPagerSupport.java। सौभाग्य!


धन्यवाद - मुझे उस पर एक नज़र होगी! शायद मैं कुछ गलत कर रहा हूँ।
मथायस

0

मैं इसमें भाग गया और बहुत समान मुद्दे थे। मैंने इसे स्टैक ओवरफ्लो पर भी पूछा

मेरे लिए, मेरे विचार के जनक के माता-पिता में किसी LinearLayoutने requestLayout()बिना बुलाए उप-भाग और ओवररोड कर दिया super.requestLayout()। इसे रोका onMeasureऔर onLayoutमेरे ViewPager पर बुलाया जा रहा है (हालांकि पदानुक्रमकर्ता मैन्युअल रूप से इन्हें कॉल करता है)। मापा जा रहा है बिना वे ViewPager में खाली दिखेंगे।

इसलिए अपने युक्तियों की जांच करें। सुनिश्चित करें कि वे दृश्य से उप-वर्ग बनाते हैं और अनुरोध पर दृष्टिहीनता या कुछ भी समान रूप से ओवरराइड नहीं करते हैं।


0

एक ही मुद्दा था, जो कुछ करना है ListView(क्योंकि मेरा खाली दृश्य ठीक दिखाता है अगर सूची खाली है)। मैंने सिर्फ requestLayout()समस्याग्रस्त पर कॉल किया ListView। अब यह ठीक है!


0

मैं एक ही समस्या में भाग गया जब एक ViewPager और FragmentStatePagerAdapter का उपयोग कर रहा था। मैंने 3 सेकंड की देरी के साथ एक हैंडलर का उपयोग करके अमान्य () और अनुरोध-सूची () को कॉल करने का प्रयास किया, लेकिन यह काम नहीं किया। क्या काम किया गया था दृश्यदर्शी की पृष्ठभूमि के रंग को निम्न प्रकार से रीसेट करना:

MyFragment.java

    private Handler mHandler;
    private Runnable mBugUpdater;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = new ViewPager(getActivity());
        //...Create your adapter and set it here...

        mHandler = new Handler();
        mBugUpdater = new Runnable(){
            @Override
            public void run() {
                mVp.setBackgroundColor(mItem.getBackgroundColor());
                mHandler = null;
                mBugUpdater = null;
            }           
        };
        mHandler.postDelayed(mBugUpdater,50);

        return rootView;
    }

    @Override
    public void onPause() {
        if(mHandler != null){
            //Remove the callback if it hasn't triggered yet
            mHandler.removeCallbacks(mBugUpdater);
            mHandler = null;
            mBugUpdater = null;
        }
        super.onPause();
     }

0

मुझे एक ही लक्षण के साथ एक समस्या थी, लेकिन एक अलग कारण जो मेरी ओर से एक मूर्खतापूर्ण गलती निकला। सोचा था कि अगर इसे कोई मदद करता है तो मैं इसे यहां जोड़ दूंगा।

मेरे पास FragmentStatePagerAdapter का उपयोग करके एक ViewPager था जिसमें दो टुकड़े होते थे, लेकिन मैंने बाद में एक तीसरा जोड़ा। हालाँकि, मैं भूल गया कि डिफ़ॉल्ट ऑफ़ स्क्रीन पृष्ठ सीमा 1 है - इसलिए, जब मैं नए तीसरे टुकड़े पर जाऊँगा, तो पहला नष्ट हो जाएगा, फिर वापस स्विच करने के बाद पुनः बनाया जाएगा। समस्या यह थी कि मेरी गतिविधि इन टुकड़ों को उनके UI स्थिति को आरंभीकृत करने के लिए सूचित करने के लिए थी। यह तब हुआ जब गतिविधि और टुकड़ा जीवनचक्र समान थे, लेकिन इसे ठीक करने के लिए मुझे अपने स्टार्टअप जीवनचक्र के दौरान अपने यूआई को आरंभ करने के लिए खंडों को बदलना पड़ा। अंत में मैंने 2 में बदलते सेटऑनस्क्रीनपेजिमिट को भी घाव कर दिया ताकि सभी तीन टुकड़े हर समय जीवित रहें (इस मामले में सुरक्षित क्योंकि वे बहुत स्मृति गहन नहीं थे)।


-1

मेरा भी ऐसा ही मुद्दा था। मैं विचारों को कैश करता हूं क्योंकि मुझे केवल 3 दृश्य चाहिए ViewPager। जब मैं आगे स्लाइड करता हूं तो सबकुछ ठीक है, लेकिन जब मैं आगे की ओर स्लाइड करना शुरू करता हूं तो त्रुटि होती है, यह कहता है कि "मेरे विचार में पहले से ही एक अभिभावक है"। समाधान मैन्युअल रूप से अनावश्यक वस्तुओं को हटाना है।

@Override
    public Object instantiateItem(ViewGroup container, int position) {
        int localPos = position % SIZE;
        TouchImageView view;
        if (touchImageViews[localPos] != null) {
            view = touchImageViews[localPos];
        } else {
            view = new TouchImageView(container.getContext());
            view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            touchImageViews[localPos] = view;
        }
        view.setImageDrawable(mDataModel.getPhoto(position));
        Log.i(IRViewPagerAdpt.class.toString(), "Add view " + view.toString() + " at pos: " + position + " " + localPos);
        if (view.getParent() == null) {
        ((ViewPager) container).addView(view);
    }
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object view) {
        //      ((ViewPager) container).removeView((View) view);
        Log.i(IRViewPagerAdpt.class.toString(), "remove view " + view.toString() + " at pos: " + position);
    }

..................

private static final int SIZE = 3;
private TouchImageView[] touchImageViews = new TouchImageView[SIZE];

-1

मेरे लिए एप्लिकेशन प्रक्रिया के मारे जाने के बाद समस्या वापस आ रही थी। मैं एंड्रॉइड स्रोतों से संशोधित कस्टम व्यू पेजर एडेप्टर का उपयोग कर रहा हूं। दृश्य पेजर सीधे गतिविधि में एम्बेडेड है।

कॉलिंग viewPager.setCurrentItem(position, true);

(एनीमेशन के साथ) डेटा सेट करने के बाद और InformDataSetChanged () काम करने लगता है, लेकिन अगर पैरामीटर झूठा करने के लिए सेट किया गया है और टुकड़ा खाली नहीं है। यह एक एज केस है जो किसी की मदद के लिए हो सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.