davideas / FlexibleAdapter

Fast and versatile Adapter for RecyclerView which regroups several features into one library to considerably improve the user experience :-)
Apache License 2.0
3.55k stars 553 forks source link

FastScroll position is incorrect after restoring from savedState whereas RecyclerView state is correct #686

Open yaroslav-shlapak opened 6 years ago

yaroslav-shlapak commented 6 years ago

FlexibleAdapeter 5.1.0, Android 9.0, Pixel 1

After restoring state of RecyclerView and FlexibleAdapter, FastScroll position is wrong or not visible. On user scrolling FastScroll handle jumps to the correct position.

This issue is visible on example apk on configuration changes on any Fragment with FastScroll.

My particular case:

  1. Save state using Evernote state lib:
@Parcelize
data class RecyclerSavedState(
        val position: Int,
        val state: Parcelable?,
        val adapterState: Bundle?
) : Parcelable
    @State
    var savedState: RecyclerSavedState? = null
    override fun onPause() {
        super.onPause()
        val state = Bundle()
        adapter?.onSaveInstanceState(state)
        savedState = RecyclerSavedState(
                adapter?.stickyPosition ?: 0,
                alertsRecycler?.layoutManager?.onSaveInstanceState(),
                state
        )
    }
  1. Observe items in Fragment:
    
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel.items.observe(viewLifecycleOwner, Observer { newAlertList ->
            newAlertList?.let { list ->
                    adapter?.submitList(list, savedState)
            })
    }
3. FlexibleAdapter extension:

class RecyclerAdapter( items: List<AbstractFlexibleItem<>>, listeners: Any ) : FlexibleAdapter<AbstractFlexibleItem<>>(items, listeners, true) { private var recyclerSavedState: RecyclerSavedState? = null

fun submitList(items: List<ItemHolder>?, recyclerSavedState: RecyclerSavedState?) {
    this.recyclerSavedState = recyclerSavedState
    this.postUpdate = postUpdate
    items?.let {
        updateDataSet(items, false)
    }
}

override fun onPostUpdate() {
    super.onPostUpdate()
    updateState()
}

private fun updateState() {
    recyclerSavedState?.let {
        recyclerView.layoutManager?.onRestoreInstanceState(it.state)
        onRestoreInstanceState(it.adapterState)
    } ?: kotlin.run {
        recyclerView?.scrollToPosition(0)
    }
}

}



Is there any way to initialize FastScroll with correct position?