Android Save and Restore RecyclerView State/Position

May 5, 2020

Fragment

class BatchFragment : Fragment() {
    private val viewModel: BatchViewModel by viewModels()


    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        initList()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        viewModel.listState = list.layoutManager?.onSaveInstanceState()

        // val layoutManager = list.layoutManager as GridLayoutManager
        // val position = layoutManager.findFirstVisibleItemPosition()
    }


    override fun initList() {
        adapter = LocalAdapter(viewModel)
        adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
            override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
                if (viewModel.listState != null) {
                    list.layoutManager?.onRestoreInstanceState(viewModel.listState)

                    // val layoutManager = list.layoutManager as GridLayoutManager
                    // layoutManager.scrollToPositionWithOffset(position, 0)
                }
            }
        })
        list.adapter = adapter

        // load items into adapter
        // adapter.submitList(...)
    }

    private class LocalAdapter(val viewModel: BatchViewModel) : ListAdapter<ViewItem, LocalAdapter.ViewHolder>(DiffCallback()) {
        // ...
    }
}

NOTE: I am using Jetpack Navigation, so I listen to onDestroyView to save state (when navigate to another fragment).

ViewModel

class BatchViewModel(application: Application) : AndroidViewModel(application) {
    var listState: Parcelable? = null
}
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.