ViewModel 상태의 ViewPager2 / Tabs 문제


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

탭이 작동 중입니다. 그러나 MergedItemsFragment의 ViewModel이 이상하게 작동하는 것으로 나타났습니다. 탭을 추가하기 전에 다음과 같이 조각으로 이동했습니다.

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

그 조각을 남겨두고 NavHostFragment.findNavController(this).popBackStack()나중에 그 조각 으로 돌아 왔을 때 새로운 빈 ViewModel을 얻습니다. 이것은 의도 된 것입니다.

새로운 접근 방식으로 나는 탐색하고 return new MergedItemsFragment()있습니다. 해당 조각을 남겨두고 나중에 반환 하면 이전 데이터포함 된 ViewModel이 나타납니다 . 사용자가 다른 조각에서 다른 데이터를 선택했기 때문에 이전 데이터는 더 이상 관련이 없기 때문에 문제가됩니다.


업데이트 # 1

나는 동일한 인쇄 문이 여러 번 호출되기 때문에 실제로 모든 이전 조각 을 메모리에 보관한다는 것을 깨달았 습니다. 호출 시간은 내가 떠나서 해당 화면으로 돌아 오는 횟수에 따라 증가합니다. 따라서 내가 10 번 떠났다가 내 장치를 돌리면 실제로 한 줄을 10 번 실행합니다. ViewModels와 작동하는 방식으로 탐색 구성 요소로 탭 / ViewPagers를 구현하는 방법이 있습니까?


업데이트 # 2

ViewModels를 다음과 같이 설정했습니다.

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

나는 같은 결과를 얻는다 :

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

Fragment 자체에서 ViewModel을 바인딩합니다. 따라서 this조각입니다.


ViewModel 설정 방법을 보여줄 수 있습니까? 또한 새로운 데이터를 가져올 때 새로운 ViewModel을 만들 수없는 이유가 있습니까?
BlackHatSamurai

내 질문을 업데이트했습니다. 자체적으로 관리하는 뷰 모델의 요점이 아닌가? 한 번 만들고 하나의 조각에 대해 지속됩니다. 새 데이터가있는 경우 어떻게 정확하게 다시 작성합니까? 왜 이전에이를 수행하지 않아도됩니까?
user123456789

프래그먼트가 파괴되었으므로 이전에 수행 할 필요가 없었습니다. 이제 ViewPager를 사용하고 있으며 조각을 메모리에 저장합니다. 필요할 때 데이터를 지우는 것이 좋습니다. VM 자체가 아닌 VM의 데이터를 관리해야합니다.
BlackHatSamurai

내가 가진 문제는 이전 VM이 실제로 이전 LiveData를 제공하고 다른 구성 요소에 이전 데이터를 제공한다는 것입니다. 따라서 이전 VM이 계속 간섭하기 때문에 데이터를 지우지 않아도됩니다. 예 : 현재 ViewModel에서 목록을 지 웁니다. 그러나 화면에는 여전히 이전 목록이 표시됩니다. ViewModel을 디버깅하고 List의 길이를 확인하면 지워지기 때문에 0이라고 표시됩니다. 유일한 논리적 설명은 이전 데이터를 제공하는 다른 ViewModel입니다.
user123456789

각 조각에 동일한 VM을 사용하고 있습니까? 아니면 각 조각마다 자체 VM이 있습니까?
BlackHatSamurai

답변:


3

귀하의 의견에 따라 Fragment를 사용하고 있으며 해당 Fragment 안에는 뷰 파서가 있습니다. 따라서 ViewPager 용 어댑터를 작성하는 동안 getActivity () 대신 childFragmentManager 를 전달해야합니다.

다음은 사용할 수있는 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
감사. 이안 한니발 라케가 이미 말했듯이 조각 자체를 전달하는 것으로 충분합니다. 적절한 구성자가 있는지 확인하십시오. 따라서 두 가지 대답이 모두 맞습니다.
user123456789
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.