Wait for adapter to contain data before attaching it to recyclerview to prevent loosing scroll position when rotating device

This commit is contained in:
Sylvain Berfini 2024-09-09 11:13:13 +02:00
parent 6c22b1f66d
commit db751efa91
11 changed files with 74 additions and 43 deletions

View file

@ -88,10 +88,6 @@ class ConferenceParticipantsListFragment : GenericCallFragment() {
binding.participantsList.setHasFixedSize(true)
binding.participantsList.layoutManager = LinearLayoutManager(requireContext())
if (binding.participantsList.adapter != adapter) {
binding.participantsList.adapter = adapter
}
binding.setBackClickListener {
findNavController().popBackStack()
}
@ -107,6 +103,12 @@ class ConferenceParticipantsListFragment : GenericCallFragment() {
viewModel.conferenceModel.participants.observe(viewLifecycleOwner) {
Log.i("$TAG participants list updated with [${it.size}] items")
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.participantsList.adapter != adapter) {
binding.participantsList.adapter = adapter
}
}
viewModel.conferenceModel.removeParticipantEvent.observe(viewLifecycleOwner) {

View file

@ -120,10 +120,6 @@ abstract class AbstractNewTransferCallFragment : GenericCallFragment() {
val headerItemDecoration = RecyclerViewHeaderDecoration(requireContext(), adapter)
binding.contactsAndSuggestionsList.addItemDecoration(headerItemDecoration)
if (binding.contactsAndSuggestionsList.adapter != adapter) {
binding.contactsAndSuggestionsList.adapter = adapter
}
adapter.onClickedEvent.observe(viewLifecycleOwner) {
it.consume { model ->
startCall(model)
@ -139,6 +135,12 @@ abstract class AbstractNewTransferCallFragment : GenericCallFragment() {
val count = adapter.itemCount
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.contactsAndSuggestionsList.adapter != adapter) {
binding.contactsAndSuggestionsList.adapter = adapter
}
if (count == 0) {
(view.parent as? ViewGroup)?.doOnPreDraw {
startPostponedEnterTransition()

View file

@ -76,10 +76,6 @@ class CallsListFragment : GenericCallFragment() {
binding.callsList.setHasFixedSize(true)
binding.callsList.layoutManager = LinearLayoutManager(requireContext())
if (binding.callsList.adapter != adapter) {
binding.callsList.adapter = adapter
}
adapter.callLongClickedEvent.observe(viewLifecycleOwner) {
it.consume { model ->
val modalBottomSheet = CallMenuDialogFragment(model) {
@ -108,6 +104,12 @@ class CallsListFragment : GenericCallFragment() {
viewModel.calls.observe(viewLifecycleOwner) {
Log.i("$TAG Calls list updated with [${it.size}] items")
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.callsList.adapter != adapter) {
binding.callsList.adapter = adapter
}
}
}

View file

@ -111,6 +111,8 @@ class ConversationForwardMessageFragment : SlidingPaneChildFragment() {
)
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.contactsList.adapter != adapter) {
binding.contactsList.adapter = adapter
}

View file

@ -400,10 +400,6 @@ open class ConversationFragment : SlidingPaneChildFragment() {
layoutManager.stackFromEnd = true
binding.eventsList.layoutManager = layoutManager
if (binding.eventsList.adapter != adapter) {
binding.eventsList.adapter = adapter
}
val callbacks = RecyclerViewSwipeUtilsCallback(
R.drawable.reply,
ConversationEventAdapter.EventViewHolder::class.java
@ -480,6 +476,12 @@ open class ConversationFragment : SlidingPaneChildFragment() {
Log.i("$TAG Events (messages) list submitted, contains [${items.size}] items")
adapter.submitList(items)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.eventsList.adapter != adapter) {
binding.eventsList.adapter = adapter
}
(view.parent as? ViewGroup)?.doOnPreDraw {
sharedViewModel.openSlidingPaneEvent.value = Event(true)
}

View file

@ -120,10 +120,6 @@ class ConversationsListFragment : AbstractMainFragment() {
binding.conversationsList.setHasFixedSize(true)
binding.conversationsList.layoutManager = LinearLayoutManager(requireContext())
if (binding.conversationsList.adapter != adapter) {
binding.conversationsList.adapter = adapter
}
adapter.conversationLongClickedEvent.observe(viewLifecycleOwner) {
it.consume { model ->
val modalBottomSheet = ConversationDialogFragment(
@ -181,6 +177,13 @@ class ConversationsListFragment : AbstractMainFragment() {
listViewModel.conversations.observe(viewLifecycleOwner) {
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.conversationsList.adapter != adapter) {
binding.conversationsList.adapter = adapter
}
Log.i("$TAG Conversations list ready with [${it.size}] items")
listViewModel.fetchInProgress.value = false
}

View file

@ -133,17 +133,17 @@ class ContactsListFragment : AbstractMainFragment() {
configureAdapter(adapter)
configureAdapter(favouritesAdapter)
if (binding.contactsList.adapter != adapter) {
binding.contactsList.adapter = adapter
}
if (binding.favouritesContactsList.adapter != favouritesAdapter) {
binding.favouritesContactsList.adapter = favouritesAdapter
}
listViewModel.contactsList.observe(
viewLifecycleOwner
) {
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.contactsList.adapter != adapter) {
binding.contactsList.adapter = adapter
}
Log.i("$TAG Contacts list updated with [${it.size}] items")
listViewModel.fetchInProgress.value = false
}
@ -152,6 +152,13 @@ class ContactsListFragment : AbstractMainFragment() {
viewLifecycleOwner
) {
favouritesAdapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.favouritesContactsList.adapter != favouritesAdapter) {
binding.favouritesContactsList.adapter = favouritesAdapter
}
Log.i("$TAG Favourites contacts list updated with [${it.size}] items")
}

View file

@ -106,10 +106,6 @@ class HistoryFragment : SlidingPaneChildFragment() {
binding.callHistory.setHasFixedSize(true)
binding.callHistory.layoutManager = LinearLayoutManager(requireContext())
if (binding.callHistory.adapter != adapter) {
binding.callHistory.adapter = adapter
}
viewModel.callLogFoundEvent.observe(viewLifecycleOwner) {
it.consume { found ->
if (found) {
@ -136,6 +132,12 @@ class HistoryFragment : SlidingPaneChildFragment() {
viewModel.historyCallLogs.observe(viewLifecycleOwner) {
Log.i("$TAG Call history list ready with [${it.size}] items")
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.callHistory.adapter != adapter) {
binding.callHistory.adapter = adapter
}
}
viewModel.historyDeletedEvent.observe(viewLifecycleOwner) {

View file

@ -107,10 +107,6 @@ class HistoryListFragment : AbstractMainFragment() {
binding.historyList.setHasFixedSize(true)
binding.historyList.layoutManager = LinearLayoutManager(requireContext())
if (binding.historyList.adapter != adapter) {
binding.historyList.adapter = adapter
}
adapter.callLogLongClickedEvent.observe(viewLifecycleOwner) {
it.consume { model ->
val modalBottomSheet = HistoryMenuDialogFragment(
@ -191,6 +187,13 @@ class HistoryListFragment : AbstractMainFragment() {
listViewModel.callLogs.observe(viewLifecycleOwner) {
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.historyList.adapter != adapter) {
binding.historyList.adapter = adapter
}
Log.i("$TAG Call logs ready with [${it.size}] items")
listViewModel.fetchInProgress.value = false
}

View file

@ -119,10 +119,6 @@ class MeetingsListFragment : AbstractMainFragment() {
val headerItemDecoration = RecyclerViewHeaderDecoration(requireContext(), adapter)
binding.meetingsList.addItemDecoration(headerItemDecoration)
if (binding.meetingsList.adapter != adapter) {
binding.meetingsList.adapter = adapter
}
binding.setNewMeetingClicked {
if (findNavController().currentDestination?.id == R.id.meetingsListFragment) {
Log.i("$TAG Navigating to schedule meeting fragment")
@ -153,6 +149,13 @@ class MeetingsListFragment : AbstractMainFragment() {
val currentCount = adapter.itemCount
val newCount = it.size
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.meetingsList.adapter != adapter) {
binding.meetingsList.adapter = adapter
}
Log.i("$TAG Meetings list ready with [$newCount] items")
listViewModel.fetchInProgress.value = false
}

View file

@ -94,13 +94,16 @@ class RecordingsListFragment : GenericMainFragment() {
val headerItemDecoration = RecyclerViewHeaderDecoration(requireContext(), adapter)
binding.recordingsList.addItemDecoration(headerItemDecoration)
if (binding.recordingsList.adapter != adapter) {
binding.recordingsList.adapter = adapter
}
listViewModel.recordings.observe(viewLifecycleOwner) {
val count = it.size
adapter.submitList(it)
// Wait for adapter to have items before setting it in the RecyclerView,
// otherwise scroll position isn't retained
if (binding.recordingsList.adapter != adapter) {
binding.recordingsList.adapter = adapter
}
Log.i("$TAG Recordings list ready with [$count] items")
listViewModel.fetchInProgress.value = false
}