I have a RecyclerView with a ListAdapter. The list that is shown in the RecyclerView comes from a Flow that is observed in the Fragment that the recyclerView is instantiated.
When the Fragment is created, the data are calculated too (in onViewCreated Method) . In the first data-calculation the RecyclerView is empty, a progressBar is shown, then the data is calculated, the progressbar hides, and the RecyclerView is populated.
If I go again in this Fragment to re-calculate the data, the previous list is shown simultaneously with the progressbar, and then is updated.
I want every time that new data is calculated to NOT show the previous list (just like the first data-calculation), but can't find a way to do it.
I tried to clear() the currentList and notifyDataSetChanged() but it still happens.. Any ideas?
Here is the code:
Fagment:
@AndroidEntryPoint
class YourPlanFragment : Fragment(R.layout.fragment_your_plan) {
lateinit var navController: NavController
private lateinit var binding: FragmentYourPlanBinding
private val sharedViewModel: WorkoutPlansViewModel by activityViewModels()
private lateinit var appBarConfiguration: AppBarConfiguration
@Inject
lateinit var dataStore: UserPreferencesRepo
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navController = Navigation.findNavController(view)
binding = FragmentYourPlanBinding.bind(view)
appBarConfiguration = AppBarConfiguration(navController.graph)
val toolbar = binding.yourPlanToolbar
toolbar.setupWithNavController(navController, appBarConfiguration)
val exerciseAdapter = DayListAdapter(DayListAdapter.OnClickListener {
navigateTo(sharedViewModel.weekIndex, it.dayNumber)
})
exerciseAdapter.currentList.clear()
exerciseAdapter.notifyDataSetChanged()
binding.recyclerViewYourPlan.apply {
adapter = exerciseAdapter
layoutManager = LinearLayoutManager(requireContext())
setHasFixedSize(true)
recycledViewPool.clear()
removeAllViews()
adapter?.notifyDataSetChanged()
}
if (!sharedViewModel.planGenerated) {
// Here the data is generated
sharedViewModel.onTriggerEvent(WorkoutPlansEvent.GetWorkoutPlanEvent)
} else if (sharedViewModel.planGenerated) {
sharedViewModel.onTriggerEvent(WorkoutPlansEvent.GetWeekEvent)
}
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
sharedViewModel.yourPlanState.collect { yourPlanState ->
when (yourPlanState.progressBarState) {
is ProgressBarState.Loading -> {
binding.progressBar.isVisible = true
}
is ProgressBarState.Idle -> {
binding.progressBar.isInvisible = true
}
}
exerciseAdapter.submitList(yourPlanState.planDays)
}
}
}
}
private fun navigateTo(
currentWeek: Int,
dayNumber: Int,
) {
val action =
YourPlanFragmentDirections.actionYourPlanFragmentToYourDayFragment(
currentWeek,
dayNumber
)
navController.navigate(action)
}
}
ListAdapter:
class DayListAdapter(private val onClickListener: OnClickListener) :
ListAdapter<Day, DayListAdapter.DayViewHolder>(ExerciseComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DayViewHolder {
val binding = ListItemDayBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return DayViewHolder(binding)
}
override fun onBindViewHolder(holder: DayViewHolder, position: Int) {
val currentItem = getItem(position)
holder.itemView.setOnClickListener {
onClickListener.onClick(currentItem)
}
if (currentItem != null) {
holder.bind(currentItem)
}
}
class DayViewHolder(private val binding: ListItemDayBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(day: Day) {
binding.apply {
dayNumber = day.dayNumber.toString()
executePendingBindings()
}
}
}
class ExerciseComparator : DiffUtil.ItemCallback<Day>() {
override fun areItemsTheSame(oldItem: Day, newItem: Day) =
oldItem.dayNumber == newItem.dayNumber
override fun areContentsTheSame(oldItem: Day, newItem: Day) =
oldItem == newItem
}
class OnClickListener(val clickListener: (day: Day) -> Unit) {
fun onClick(day: Day) = clickListener(day)
}
}
CodePudding user response:
This is happing because of the activityViewModels()
that will preserve the viewmodel based on activity lifecycle. Either create WorkoutPlansViewModel
using viewmodels()
or Try to clear the list from the WorkoutPlansViewModel
when you are creating the fragment.