ViewMagerel राज्य के साथ ViewPager2 / टैब समस्या


9

मैं MVVM पैटर्न का अनुसरण कर रहा हूं - जिसका अर्थ है कि मेरे पास प्रत्येक फ्रेग्मेंट के लिए एक ViewModel है।

मैंने ViewPager2 का उपयोग करके दो टैब जोड़े ।

मेरा एडॉप्टर ऐसा दिखता है:

@Override
public Fragment createFragment(int position) {
    switch (position) {
        case 0:
            return new MergedItemsFragment();
        case 1:     
            return new ValidatedMergedItemsFragment();
    }
    return new MergedItemsFragment();
}

टैब काम कर रहे हैं। हालाँकि, मैंने देखा कि मेरे मर्जमैडमफ्रेम का दृश्यमॉडल अजीब व्यवहार कर रहा है। इससे पहले कि मैं इस तरह से फ्रेग्मेंट में नेविगेट किया गया टैब जोड़ा:

NavHostFragment.findNavController(this).navigate(R.id.action_roomFragment_to_itemsFragment);

जब मैंने उस टुकड़े को छोड़ दिया NavHostFragment.findNavController(this).popBackStack()और बाद में उस खंड में वापस आ गया तो मुझे एक नया खाली दृश्यमॉडल मिलेगा। यह इरादा था।

नए दृष्टिकोण के साथ मैं नेविगेट कर रहा हूं return new MergedItemsFragment()। जब मैं उस टुकड़े को छोड़ता हूं और बाद में वापस आता हूं तो मुझे एक ViewModel मिल रहा है जिसमें पुराना डेटा है । यह एक मुद्दा है क्योंकि पुराना डेटा अब प्रासंगिक नहीं है क्योंकि उपयोगकर्ता ने किसी अन्य टुकड़े में भिन्न डेटा का चयन किया है।


अपडेट # 1

मुझे एहसास हुआ कि वह वास्तव में सभी पुराने फ़्रैगमेंट्स को स्मृति में रखता है क्योंकि एक ही प्रिंट स्टेटमेंट को कई बार कहा जाता है। जिस समय को मैं स्क्रीन पर छोड़ता हूं और उस स्क्रीन पर वापस लौटता हूं, इसे बढ़ाना कहा जाता है। इसलिए अगर मैं 10 बार लौटता हूं और अपने डिवाइस को घुमाता हूं तो वह वास्तव में 10 बार एक लाइन को निष्पादित करेगा। कोई भी अनुमान लगाता है कि नेविगेशन घटकों के साथ टैब / व्यूपैंसर्स को कैसे लागू किया जाए जो कि व्यूमॉडल के साथ काम करता है?


अद्यतन # 2

मैंने अपना ViewModels इस तरह सेट किया:

viewModel = new ViewModelProvider(this, providerFactory).get(MergedItemViewModel.class)

मुझे इसके परिणाम समान मिलते हैं:

viewModel = ViewModelProviders.of(this).get(MergedItemViewModel.class);

मैं ViewModel को ही खंड में बांधता हूं। इसलिए, thisफ्रैगमेंट है।


क्या आप दिखा सकते हैं कि आप अपना ViewModels कैसे सेट कर रहे हैं? इसके अलावा, क्या कोई कारण है कि जब आप नया डेटा प्राप्त करते हैं तो आप एक नया ViewModel नहीं बना सकते हैं?
ब्लैकहैटसमुरी

मैंने अपना प्रश्न अपडेट कर दिया है। क्या एक नजरिया की बात नहीं है कि वह खुद का ख्याल रखे? मैं इसे एक बार बनाता हूं और यह एक टुकड़े के लिए बनी रहती है। यदि मेरे पास नया डेटा है तो मैं इसे फिर से कैसे बनाऊंगा और मुझे पहले ऐसा करने की आवश्यकता क्यों नहीं थी?
user123456789

टुकड़ा नष्ट हो गया था क्योंकि इससे पहले आपको इसे करने की आवश्यकता नहीं थी। अब आप एक ViewPager का उपयोग कर रहे हैं और यह मेमोरी में टुकड़े को स्टोर करता है। मेरा सुझाव है कि जब आपको आवश्यकता हो, तो केवल डेटा को साफ़ करें। आपको VM के बजाय VM में डेटा को प्रबंधित करने की आवश्यकता है।
ब्लैकहैटसमुरी

मेरे पास समस्या यह है कि पुराने VM अभी भी पुराने LiveData की सेवा कर रहे हैं और अन्य घटकों को पुराने डेटा को खिला रहे हैं। इसलिए डेटा साफ़ करने से ऐसा नहीं होगा क्योंकि पुराने VMs हस्तक्षेप करते रहते हैं। उदाहरण: मैं वर्तमान ViewModel में एक सूची साफ़ करता हूं। हालाँकि स्क्रीन को अभी भी पुरानी सूची मिली है। जब मैं ViewModel को डिबग करता हूं और सूची की लंबाई की जांच करता है तो यह 0 कहती है - क्योंकि यह साफ हो चुका है। केवल तार्किक स्पष्टीकरण अन्य ViewModels पुराने डेटा की सेवा कर रहे हैं।
user123456789

क्या आप प्रत्येक टुकड़े के लिए एक ही वीएम का उपयोग कर रहे हैं? या प्रत्येक टुकड़े का अपना VM है?
ब्लैकहैटसमुरी

जवाबों:


3

आपकी टिप्पणी के अनुसार, आप Fragment का उपयोग कर रहे हैं और उस Fragment के अंदर आपका viewpager है। तो ViewPager के लिए अपना एडॉप्टर बनाते समय आपको getActivity () के बजाय चाइल्डफ्रैगमेंट मैनजर पास करना होगा।

नीचे आपके देखने के लिए एक नमूना एडाप्टर है जिसे आप उपयोग कर सकते हैं

class NewViewPagerAdapter(fm: FragmentManager, behavior: Int) : FragmentStatePagerAdapter(fm, behavior) {
    private val mFragmentList: MutableList<Fragment> = ArrayList()
    private val mFragmentTitleList: MutableList<String> = ArrayList()

    override fun getItem(position: Int): Fragment {
        return mFragmentList[position]
    }

    override fun getCount(): Int {
        return mFragmentList.size
    }

    fun addFragment(fragment: Fragment, title: String) {
        mFragmentList.add(fragment)
        mFragmentTitleList.add(title)
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return mFragmentTitleList[position]
    }
}

और अपना एडेप्टर बनाते समय इसे पसंद करें

   val adapter = NewViewPagerAdapter(
        childFragmentManager,
        FragmentPagerAdapter.POSITION_UNCHANGED
    )

मानो आप के लिए प्रलेखन देखते हैं FragmentStatePagerAdapter के यह बताता है कि आपको अपने एडेप्टर के निर्माता के अंदर (FragmentManager, int) पास होना चाहिए

मुझे उम्मीद है कि यह आपके मुद्दे को हल कर देगा क्योंकि मैं एक दिन उसी मुद्दे का सामना कर रहा था।

खुश कोडिंग।


1
धन्यवाद। जैसा कि ianhanniballake ने पहले ही कहा था, टुकड़े में पास होना ही पर्याप्त है, बस यह सुनिश्चित करें कि आपके पास एक उपयुक्त अवरोधक है। लिहाजा दोनों ही खामियां सही हैं।
user123456789
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.