ViewModel durumuyla ViewPager2 / Sekmeler sorunu


9

Ben MVVM desen takip ediyorum - yani her Parça için bir ViewModel var.

ViewPager2'yi kullanarak iki sekme ekledim .

Adaptörüm şöyle:

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

Sekmeler çalışıyor. Ancak, benim MergedItemsFragment ViewModel garip davranıyor fark ettim. Sekme eklemeden önce Fragment'e şu şekilde gittim:

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

Bu parçayı bırakıp NavHostFragment.findNavController(this).popBackStack()daha sonra bu parçasına döndüğümde yeni bir boş ViewModel alırdım. Bu amaçlanmıştı.

Yeni yaklaşımla birlikte ilerliyorum return new MergedItemsFragment(). Bu parçayı bıraktığımda ve daha sonra geri döndüğümde eski verileri içeren bir ViewModel alıyorum . Bu, Kullanıcı başka bir parçada farklı veriler seçtiği için eski verilerin artık alakalı olmadığı için bir sorundur.


Güncelleme # 1

Aslında tüm eski Fragmanları hafızada tuttuğunu fark ettim çünkü aynı baskı ifadeleri birden çok kez çağrılır. Adı verilen süreler, o ekrana gitme ve geri dönme süremle birlikte artar. Bu yüzden 10 kez ayrılıp geri dönersem ve cihazımı döndürürsem, aslında 10 kez bir satır yürütür. Herhangi bir sekme / ViewPagers Gezinti Bileşenleri ile ViewModels ile çalışan bir şekilde nasıl uygulanacağını tahmin?


Güncelleme # 2

ViewModels'ımı şöyle ayarladım:

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

İle aynı sonuçları elde:

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

ViewModel'i Fragment'ın kendisine bağlarım. Bu nedenle, thisParçadır.


ViewModellerinizi nasıl ayarladığınızı gösterebilir misiniz? Ayrıca, yeni veriler aldığınızda yalnızca yeni bir ViewModel oluşturamamanızın bir nedeni var mı?
BlackHatSamurai

Sorumu güncelledim. Bir görünüm modelinin kendisi bununla ilgileniyor değil mi? Bir kez yaratıyorum ve bir parça için devam ediyor. Yeni verilerim olması durumunda tam olarak nasıl yeniden oluşturabilirim ve bunu neden daha önce yapmam gerekmiyordu?
user123456789

Daha önce yapmanız gerekmiyordu, çünkü parça yok edildi. Şimdi bir ViewPager kullanıyorsunuz ve parçayı hafızada saklıyor. Sadece gerektiğinde verileri silmenizi öneririm. Verileri sanal makinenin kendisi yerine sanal makinede yönetmeniz gerekir.
BlackHatSamurai

Benim sorunum eski VM'ler aslında hala eski LiveData hizmet ve diğer bileşenleri eski veri besleme olmasıdır. Bu nedenle, eski VM'ler müdahale etmeye devam ettiği için verileri temizlemek işe yaramaz. Örnek: Geçerli ViewModel'deki bir listeyi temizlerim. Ancak ekran hala eski listeyi alır. ViewModel'de hata ayıkladığımda ve Listenin uzunluğunu kontrol ettiğimde temizlendiğinden 0 diyor. Tek mantıklı açıklama eski verilere hizmet veren diğer ViewModeller'lerdir.
user123456789

Parçaların her biri için aynı VM'yi mi kullanıyorsunuz? Yoksa her parçanın kendi VM'si var mı?
BlackHatSamurai

Yanıtlar:


3

Yorumunuza göre, Fragment'ı kullanıyorsunuz ve bu Fragment'ın içinde görüntüleyiciniz var. Bu nedenle ViewPager için Bağdaştırıcınızı oluştururken getActivity () yerine childFragmentManager'ı geçirmeniz gerekir

Aşağıda, görünümünüz için kullanabileceğiniz örnek bir Adaptör bulunmaktadır

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]
    }
}

ve adaptörünüzü oluştururken

   val adapter = NewViewPagerAdapter(
        childFragmentManager,
        FragmentPagerAdapter.POSITION_UNCHANGED
    )

sanki FragmentStatePagerAdapter belgelerini görüyormuşsunuz gibi adaptörünüzün yapıcısına (FragmentManager, int) geçmeniz gerektiğini belirtiyor

Umarım bir gün aynı sorunla karşılaştığımda bu sorununuzu çözecektir.

Mutlu kodlama.


1
Teşekkürler. Ianhanniballake'in daha önce de söylediği gibi, parçanın içinden geçmek yeterlidir, sadece uygun bir yapıcıya sahip olduğunuzdan emin olun. Yani her iki cevap da doğrudur.
user123456789
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.