0

I have a two fragments and one of which contains RecyclerView (the data comes from the Firebase). For example, a user clicks on an item and opens a fragment with a description, and then if he returns back need to save the scroll state of the RecyclerView. I have tried to use onScrollStateChanged() with SharedPreferences, but the state is not saved.

My code:

private lateinit var binding: FragmentListBinding

private lateinit var rvAdapter: RvStatesAdapter
private var statesList = ArrayList<State>()
private var databaseReferenceStates: DatabaseReference? = null
private lateinit var sharedPreferences: SharedPreferences
private var lastPosition by Delegates.notNull<Int>()

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    binding = FragmentListBinding.inflate(inflater, container, false)

    initDatabase()
    getStates()

    binding.rvStates.layoutManager = LinearLayoutManager(requireContext())

    binding.rvStates.addOnScrollListener(object: RecyclerView.OnScrollListener() {
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)

            lastPosition = (recyclerView.layoutManager as LinearLayoutManager?)!!.findFirstVisibleItemPosition()
        }
    })

    return binding.root
}

override fun onResume() {
    super.onResume()

    getLastPositionFromRecyclerView()
}

private fun getLastPositionFromRecyclerView() {
    val statePrefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
    lastPosition = statePrefs.getInt("lastPosition", 0)

    (binding.rvStates.layoutManager as LinearLayoutManager?)!!.scrollToPosition(lastPosition)
}

override fun onPause() {
    super.onPause()

    saveStateOfRecyclerView()
}

private fun saveStateOfRecyclerView() {
    val statePrefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
    val editor: SharedPreferences.Editor = statePrefs.edit()

    editor.putInt("lastPosition", lastPosition)
    editor.apply()
}

private fun getStates() {
    databaseReferenceStates?.addValueEventListener(object: ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            if (snapshot.exists()) {
                for (stateSnapshot in snapshot.children) {
                    val state = stateSnapshot.getValue(State::class.java)

                    statesList.add(state!!)
                }

                rvAdapter = RvStatesAdapter(statesList)
                binding.rvStates.adapter = rvAdapter
            }
        }

        override fun onCancelled(error: DatabaseError) {

        }
    })
}

private fun initDatabase() {
    FirebaseApp.initializeApp(requireContext());
    databaseReferenceStates = FirebaseDatabase.getInstance().getReference("States")
}
}
onesector
  • 361
  • 5
  • 18
  • You re using this method getLastPositionFromRecyclerView() , which calls linearlayout manager to set the position , try to instead use binding.recyclerview.scrollToPosition(getLastPositionFromRecyclerView()) and make sure the function is return an int value ( position in your case ) – Taki Aug 24 '21 at 23:40
  • 2
    You don't need to do any literally any of this. Did you read the [Restore RecyclerView scroll position blog post](https://medium.com/androiddevelopers/restore-recyclerview-scroll-position-a8fbdc9a9334)? – ianhanniballake Aug 25 '21 at 02:23
  • Make use of SaveInstanceState in your adapter and save the needed stuffs . – Karunesh Palekar Aug 25 '21 at 07:38

0 Answers0