Home > Software design >  ViewPager2 Adapter isn't reset after a restore instance state
ViewPager2 Adapter isn't reset after a restore instance state

Time:11-22

I need to setup ViewPager2 in a way where I dynamically update the Fragments that are displayed within the ViewPager2.

To facilitate this, I've created a view model LiveData object that includes a list of items that represent the data the fragments should display:

val items: LiveData<List<Item>>

In my Fragment that contains the ViewPager2, in onViewCreated I setup observing the items:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel.items.observe(viewLifecycleOwner) { items ->
        binding.viewPager.adapter = createFragmentStateAdapter(items)
    }
}

This is all working fine except when I test with "Don't keep activities" turned on. When I background/foreground the app I see that the Fragment containing the ViewPager2 is recreated and that the items observable is broadcasting an update. However, for some reason the ViewPager2 is showing an older Fragment and appears to be ignoring the new adapter that is created in the items observe block.

How do I get the ViewPager2 to update correctly when the adapter changes?

I believe what might be happening is that the ViewPager2 is trying to restore its own state but in the process is ignoring recent changes to the adapter to use.

CodePudding user response:

I found a solution by overriding getItemId and containsItem in the FragmentStateAdapter I was using

CodePudding user response:

Adapter creation should not be placed in observe, because it will create an Adapter every time the data is updated. The adapter should be created in viewCreated, and there are operations to add data and update the UI inside the Adapter.

    class DemoAdapter: RecyclerView.Adapter<DemoAdapter.VHolder>(){
        class VHolder(view: View): RecyclerView.ViewHolder(view)
        
        private var dataList: List<String> = emptyList()
        
        fun setDataList(dataList: List<String>) {
            this.dataList = dataList
            notifyDataSetChanged()
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VHolder {
            // create ViewHolder
            return VHolder(View(parent.context))
        }

        override fun onBindViewHolder(holder: VHolder, position: Int) {
           // bind data
        }

        override fun getItemCount(): Int {
            
        }
    }
val adapter = DemoAdapter()
binding.viewPager.adapter = adapter
viewModel.items.observe(viewLifecycleOwner) { items ->
    adapter.setDataList(items)
}
  • Related