ViewPager.setOffscreenPageLimit (0) अपेक्षा के अनुरूप काम नहीं करता है


100

मेरे ViewPagerउदाहरण में मेरे द्वारा उपयोग किए जाने वाले टुकड़े काफी संसाधन गहन हैं, इसलिए मैं केवल एक समय में एक लोड करना चाहूंगा। जब मैं निम्नलिखित प्रयास करता हूं:

mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);

मेरे FragmentStatePagerAdapter.getItem(int position)ओवरराइड फ़ंक्शन को 3 बार कहा जाता है, जो कि मेरे कॉल करने पर होता है mViewPager.setOffscreenPageLimit(1)। मुझे उम्मीद है कि इसे केवल एक बार बुलाया जाएगा, क्योंकि मैंने 0 ऑफस्क्रीन पेज निर्दिष्ट किए हैं।

मेरा मानना ​​है कि मैं सब कुछ सही ढंग से कह रहा हूं, क्योंकि अगर मैं फोन करता हूं mViewPager.setOffscreenPageLimit(2), तो मुझे FragmentStatePagerAdapter.getItem(int position)उम्मीद है कि 5 बार कॉल किया जाएगा।

क्या ViewPager को न्यूनतम 1 ऑफ़स्क्रीन पृष्ठों की आवश्यकता है, या क्या मैं यहां कुछ गलत कर रहा हूं?


9
मैंने एक सुविधा अनुरोध जोड़ा है: code.google.com/p/android/issues/detail?id=56667
Mark


मेरे पास केवल 3 टैब थे और सेटिंग ViewPager.setOffscreenPageLimit(2)ने मेरे लिए काम किया। कोशिश करेंViewPager.setOffscreenPageLimit(totTabs - 1)
सिबिन

जवाबों:


112

क्या ViewPager को न्यूनतम 1 ऑफ़स्क्रीन पृष्ठों की आवश्यकता है

हाँ। यदि मैं स्रोत कोड को सही ढंग से पढ़ रहा हूं, तो आपको LogCat में इस बारे में चेतावनी मिलनी चाहिए, कुछ इस तरह से:

Requested offscreen page limit 0 too small; defaulting to 1

6
यह कोई हल नहीं है! मैं केवल 1 टुकड़ा लोड नहीं करना चाहता हूं 2. निश्चित रूप से यह किसी भी तरह संभव है?
HGPB

14
@ हेराल्डो: "निश्चित रूप से यह किसी भी तरह संभव है?" - साथ नहीं ViewPagerViewPagerइन अंशों को बनाता है ताकि दृश्य मौजूद हों, इसलिए उपयोगकर्ता उनके बीच स्वाइप कर सकता है, जिसमें स्क्रीन पर फिसलने वाले पुराने दृश्य और स्क्रीन पर फिसलने वाले नए दृश्य को दिखाया जा रहा है। आपका स्वागत है ViewPagerकि आप अपना लिखने का प्रयास करें जो उन चीजों के बीच स्वाइप कर सकता है जो मौजूद नहीं हैं। आप इसके बारे में और अधिक पढ़ सकते हैं। code.google.com/p/android/issues/detail?id=56667#c3
CommonsWare

2
हां, मैंने इस मुद्दे को पढ़ा है। बस तार्किक नहीं है। मैं setOffscreenPageLimit(0)0. करने में सक्षम होने की उम्मीद करता हूं । फिर मैं स्वयं परिणामों से निपट सकता हूं। एक डिफ़ॉल्ट खाली टुकड़ा उदाहरण के लिए एक प्लेसहोल्डर हो सकता है जब तक कि कोई टुकड़ा लोड नहीं हुआ है। जिनमें से सभी UI थ्रेड को बंद कर सकते हैं। वैसे भी मैंने इसके बारे में ज्यादा नहीं सोचा है।
HGPB

5
@ हेराल्डो: "एक डिफ़ॉल्ट खाली टुकड़ा उदाहरण के लिए एक प्लेसहोल्डर हो सकता है जब तक कि लोगों ने लोड नहीं किया है" - आज, आपके मौजूदा टुकड़े के ViewPagerस्थान के साथ, आपके उपलब्ध स्थान पर वास्तविक सामग्री के साथ प्रतिस्थापित करने पर आपका स्वागत है। ।
कॉमन्सवेयर जूल

2
onPageChangeListener समाधान की तरह लगता है।
एलिकेनब्यूरट

123

मुझे जो सबसे अच्छा तरीका मिला, वह था सेटवेयरविजिहिंट
इसे आपके टुकड़े में जोड़ें

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}

1
इस समाधान के लिए ++++++ !!! धन्यवाद, इस कोड को जोड़ने के बाद मुझे पहली बार एनपीएल मिला, मैंने अभी-अभी ट्रायल कैच ब्लॉक जोड़ा और इसके काम मेरे लिए एकदम सही हैं !!!
भाविन चौहान

1
इसका उपयोग करने पर यह दूसरी स्क्रीन पर अपने लोडिंग डेटा के दूसरे टुकड़े पर दूसरे दृश्य पेजर पर तारीख को लोड नहीं करता है। क्या कोई मेरी मदद कर सकता है?
अरशद

क्या मुझे कुछ याद आ रहा है, setUserVanishHint ने onCreateView से पहले फोन किया
एंटोन

सबसे अच्छा समाधान अब पदावनत है
M.Sameer

@ M.Sameer के लिए कोई विकल्प setUserVanishHint के लिए सही नहीं है?
युदि कर्म

8

आप इस तरह की कोशिश कर सकते हैं:

public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}

protected abstract void lazyLoad();
protected void onInvisible(){}

सबसे अच्छा जवाब!
राधेश

7

पहले जोड़ें

   boolean isFragmentLoaded = false;

से

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && !isFragmentLoaded) {
        //Load Your Data Here like.... new GetContacts().execute();

        isFragmentLoaded = true;
    }
else{
     }
}

6
लेकिन यह तरीका onCreateView
AndroidGeek

2

ViewPager अगले पृष्ठ (Fragment) को लोड करने के लिए डिफ़ॉल्ट है जिसे आप setOffscreenPageLimit (0) द्वारा परिवर्तित नहीं कर सकते हैं। लेकिन आप हैक करने के लिए कुछ कर सकते हैं। आप ViewPager युक्त गतिविधि में onPageSelected फ़ंक्शन को लागू कर सकते हैं। अगले Fragment में (जिसे आप लोड नहीं करना चाहते हैं), आप एक फंक्शन लिखते हैं आइए showViewContent () कहते हैं, जहाँ आप सभी संसाधन खपत init कोड डालते हैं और onResume () विधि से पहले कुछ भी नहीं करते हैं। फिर शो व्यू कॉन्टेंट () फंक्शन ऑनपेज सेलेक्टेड को कॉल करें। आशा है कि यह मदद करेगा।


1

यह पुराना धागा हो सकता है लेकिन यह मेरे लिए काम करता है। इस फ़ंक्शन को ओवरराइड करें:

@Override
public void setMenuVisibility(boolean menuVisible) { 
    super.setMenuVisibility(menuVisible);

    if ( menuVisible ) {
        /**
         * Load your stuffs here.
         */
    } else  { 
        /**
         * Fragment not currently Visible.
         */
    } 
}

खुश कोडिंग ...


वेब पर क्या है? मेरा सुझाव है कि आप इसके लिए एक नया सूत्र बनाएँ।
राल्फगैब

1

मेरे मामले में मैं विचारों में कुछ एनिमेशन शुरू करना चाहता था, लेकिन setUserVanishHint के साथ कुछ मुद्दे मिले ...
मेरा समाधान है:

आपके एडॉप्टर के लिए 1 / addOnPageChangeListener:

mViewPager.addOnPageChangeListener(this);

2 / कार्यान्वयन OnPageChangeListener:

public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener

3/3 मेथोड को ओवरराइड करें:

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{

}

@Override
public void onPageSelected(int position)
{ 
}

@Override
public void onPageScrollStateChanged(int state)
{
}

4 / घोषित करें और अपनी कक्षा पर इस चर को शुरू करें

private static int mTabState = 1;

सूचना : मेरे एडेप्टर में तीन टुकड़े हैं, और सेटट्रेक्ट इट के लिए mTabState का उपयोग करें और एडॉप्टर की वर्तमान स्थिति जो पहचानती है कि कौन सा टुकड़ा उपयोगकर्ता को समय में दिखा है ... 5 / onPageSelected पद्धति में यह कोड जोड़ें:

if (mTabState == 0 || position == 0)
    {
        Intent intent = new Intent("animation");
        intent.putExtra("current_position", position);
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
    }

यदि पिछला पृष्ठ या वर्तमान पृष्ठ पृष्ठ 0 है (स्थिति 0 में विखंडन) तो यह सामान करें

6 / अब आपके खंड वर्ग (एडॉप्टर की स्थिति 0 में टुकड़ा), आपको ब्रॉडकास्ट रिसीवर बनाना होगा और इसे ऑन-ऑन विधि में पंजीकृत करना होगा और इसे अनधिकृत करना चाहिए:

BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (Objects.equals(intent.getAction(), "animation"))
        {
            int currentPosition = intent.getIntExtra("current_position", 0);
            if (currentPosition == 0)
            {
                startAnimation();
                setViewsVisible();
            } else
            {
                setViewsInvisible();
            }
        }
    }
};

@Override
public void onResume()
{
    super.onResume();
    LocalBroadcastManager.getInstance(mContext).registerReceiver(broadcastReceiver, new IntentFilter("animation"));
}

@Override
public void onPause()
{
    super.onPause();
    LocalBroadcastManager.getInstance(mContext).unregisterReceiver(broadcastReceiver);
}

सारांश: मेरे पास फ्रैगरमेंट पेजर एडेप्टर चुड़ैल है इसमें तीन फ्रैगमेंट्स दिखाए गए हैं, मैं एडॉप्टर की स्थिति 0 में व्यू ऑन फ्रैगमेंट में कुछ एनिमेशन दिखाना चाहता हूं, इसके लिए मैं ब्रॉडकास्टसीवर का उपयोग करता हूं। जब Fragment उठाया जाता है तो मैं एनिमेशन विधि शुरू करता हूं और उपयोगकर्ता को दृश्य दिखाता हूं, जब Fragment उपयोगकर्ता को नहीं दिखा रहा होता है तो मैं अदृश्य दृश्य की कोशिश करता हूं ...


1

Viewpager में ताज़ा दृश्य के समाधान के लिए कृपया इस कोड को आज़माएं ...।

/* DO NOT FORGET! The ViewPager requires at least “1” minimum OffscreenPageLimit */
int limit = (mAdapter.getCount() > 1 ? mAdapter.getCount() - 1 : 1);
mViewPager.setOffscreenPageLimit(limit);

0

"InstantiateItem" फ़ंक्शन के लिए, बस टुकड़ा तैयार करें, लेकिन भारी सामग्री को लोड न करें।

"OnPageChangeListener" का उपयोग करें, ताकि हर बार जब आप किसी विशिष्ट पृष्ठ पर जाएं, तो आप इसकी भारी सामग्री लोड करें और इसे दिखाएं।


0

मुझे एक ही तरह की समस्या है। मुझे इस साइट पर कुछ उपयोगी कोड मिले और इसे बदलना चाहिए।

MViewPager.setOffscreenPageLimit (...) के लिए मिनट इंट; 1 है, इसलिए यदि आप इसे 0 में बदलते हैं, तब भी आपके पास 2 पेज लोड होंगे।

पहली बात यह है कि हम एक स्थिर इंट बनाने के लिए है जिसे हम maxPageCount कहेंगे और MaxPageCount को वापस करने के लिए FragmentStatePagerAdapter विधि getCount () को ओवरराइड करें:

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

तब किसी भी स्थान से सुलभ एक स्थैतिक विधि बनाएँ, जो आपको इस अधिकतमकाउंट को बदलने की अनुमति देगा:

public static void addPage(){
    maxPageCount++; //or maxPageCount = fragmentPosition+2
    mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}

अब maxPageCount को प्रारंभ करें 1. जब आप कभी चाहें तब आप एक और पेज जोड़ सकते हैं। मेरे मामले में जब मुझे दूसरे पेज को जेनरेट करने से पहले उपयोगकर्ता को पहले पेज का इलाज करने की आवश्यकता थी। वह इसे करता है और फिर, समस्या के बिना अगले पृष्ठ पर स्वाइप कर सकता है।

आशा है कि यह किसी की मदद करेगा।


0

डेटा // निजी बूलियन लाने के लिए इस बूलियन का उपयोग करें।

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getView() != null) {
        isViewShown = true;
        // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
        fetchData();
    } else {
        isViewShown = false;
    }
} 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.