Home > other >  How to clear RecyclerView when updating data?
How to clear RecyclerView when updating data?

Time:08-24

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.

  • Related