ปัญหา ViewPager2 / แท็บกับสถานะ ViewModel


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();
}

แท็บกำลังทำงาน อย่างไรก็ตามฉันสังเกตเห็นว่า ViewModel ของ MergedItemsFragment ของฉันทำงานผิดปกติ ก่อนที่ฉันจะเพิ่มแท็บฉันไปที่ Fragment เช่นนี้:

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

เมื่อฉันออกจากส่วนนั้นด้วยNavHostFragment.findNavController(this).popBackStack()และหลังจากนั้นกลับสู่ชิ้นส่วนนั้นฉันจะได้รับ ViewModel ที่ว่างเปล่าใหม่ นี่ตั้งใจไว้

return new MergedItemsFragment()ด้วยวิธีการใหม่ฉันกำลังการนำทางด้วย เมื่อฉันออกจากส่วนที่และต่อมาในการกลับมาฉันได้รับ ViewModel ที่มีข้อมูลเก่า นั่นเป็นปัญหาเนื่องจากข้อมูลเก่าไม่เกี่ยวข้องอีกต่อไปเพราะผู้ใช้เลือกข้อมูลที่แตกต่างในส่วนอื่น


อัปเดต # 1

ฉันรู้ว่าจริง ๆ แล้วเขาช่วยให้ทุกเก่าเศษในความทรงจำเพราะงบพิมพ์เดียวกันได้รับการเรียกหลายครั้ง จำนวนครั้งที่เรียกว่าเพิ่มขึ้นตามจำนวนครั้งที่ฉันออกไปและกลับไปที่หน้าจอนั้น ดังนั้นถ้าฉันออกไปและกลับมา 10 ครั้งแล้วหมุนอุปกรณ์ของฉันเขาจะรันหนึ่งบรรทัด 10 ครั้ง มีการเดาว่าจะใช้ Tabs / ViewPagers กับ Navigation Components ในลักษณะที่ทำงานกับ ViewModels ได้อย่างไร?


อัปเดต # 2

ฉันตั้ง ViewModels ของฉันเช่นนี้:

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

ฉันได้รับผลลัพธ์เดียวกันกับ:

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

ฉันผูก ViewModel ในแฟรกเมนต์เอง ดังนั้นจึงthisเป็นส่วน


คุณสามารถแสดงวิธีการตั้งค่า ViewModels ของคุณได้หรือไม่? นอกจากนี้มีเหตุผลใดที่คุณไม่สามารถสร้าง ViewModel ใหม่เมื่อคุณได้รับข้อมูลใหม่ได้หรือไม่?
BlackHatSamurai

ฉันได้อัปเดตคำถามของฉันแล้ว ไม่ใช่โมเดลของวิวเวอร์ที่ดูแลตัวเองใช่มั้ย ฉันสร้างมันครั้งเดียวและมันยังคงอยู่สำหรับส่วนหนึ่ง ฉันจะสร้างใหม่ได้อย่างไรในกรณีที่ฉันมีข้อมูลใหม่และทำไมฉันไม่จำเป็นต้องทำก่อนหน้านี้
123456789

คุณไม่จำเป็นต้องทำก่อนเพราะชิ้นส่วนถูกทำลาย ตอนนี้คุณกำลังใช้ ViewPager และมันเก็บส่วนในหน่วยความจำ ฉันอยากจะแนะนำเพียงแค่ล้างข้อมูลเมื่อคุณต้องการ คุณต้องจัดการข้อมูลใน VM ไม่ใช่ VM เอง
BlackHatSamurai

ปัญหาที่ฉันมีคือการที่ VM เก่ายังคงให้บริการ LiveData เก่าและให้ข้อมูลแก่ส่วนประกอบอื่น ๆ ดังนั้นการล้างข้อมูลจะไม่ทำเพราะ VMs เก่ายังคงรบกวนอยู่ ตัวอย่าง: ฉันล้างรายการใน ViewModel ปัจจุบัน อย่างไรก็ตามหน้าจอยังคงได้รับรายการเก่า เมื่อฉันตรวจแก้จุดบกพร่อง ViewModel และตรวจสอบความยาวของรายการมันบอกว่า 0 - เนื่องจากมันได้รับการล้าง คำอธิบายเชิงตรรกะเพียงคำเดียวคือ ViewModels อื่น ๆ ที่ให้บริการข้อมูลเก่า
123456789

คุณใช้ VM เดียวกันสำหรับแต่ละแฟรกเมนต์หรือไม่ หรือแต่ละส่วนมี VM ของตัวเองหรือไม่
BlackHatSamurai

คำตอบ:


3

ตามความคิดเห็นของคุณคุณกำลังใช้แฟรกเมนต์และภายในแฟรกเมนต์นั้นมีวิวเวอร์ของคุณ ดังนั้นในขณะที่สร้างอะแดปเตอร์สำหรับ ViewPager คุณต้องผ่านchildFragmentManagerแทนgetActivity ()

ด้านล่างเป็นตัวอย่างอะแดปเตอร์สำหรับ viewPager ของคุณที่คุณสามารถใช้ได้

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 พูดไปแล้วการส่งผ่านชิ้นส่วนเองก็เพียงพอแล้วเพียงตรวจสอบให้แน่ใจว่าคุณมีโครงสร้างที่เหมาะสม ดังนั้นคำตอบทั้งคู่จึงถูกต้อง
123456789
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.