This problem is asked multiple time on StackOverflow, so i decided to make this project and solve your problem.
RecyclerView flickering when scrolled because we are creating Timer inside onBindViewHolder()
method. And as you know onBindViewHolder()
method is called every time when we scroll RecyclerView. Because RecyclerView reuse views to prevent from memory problems. The best thing here would be to move the CountDownTimer in the ViewHolder as a reference, cancel it before binding the data (if started) and rescheduling to the desired duration.
onBindViewHolder()
.package com.learnpainless.recyclerviewcountdowntimer;import android.os.Handler;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {private OnItemClickListener onItemClickListener;private Handler handler = new Handler();public RecyclerViewAdapter(OnItemClickListener onItemClickListener) {this.onItemClickListener = onItemClickListener;}public void clearAll() {handler.removeCallbacksAndMessages(null);}public class ViewHolder extends RecyclerView.ViewHolder {TextView timeStamp;ImageView imageView;CountdownRunnable countdownRunnable;public ViewHolder(View itemView) {super(itemView);timeStamp = itemView.findViewById(R.id.timestamp);imageView = itemView.findViewById(R.id.image_view);countdownRunnable = new CountdownRunnable(handler,timeStamp,10000,imageView);}public void bind(final OnItemClickListener listener) {handler.removeCallbacks(countdownRunnable);countdownRunnable.holder = timeStamp;countdownRunnable.millisUntilFinished = 10000 * getAdapterPosition(); //because i want all timers run separately.handler.postDelayed(countdownRunnable, 100);}}@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);return new ViewHolder(view);}@Override public void onBindViewHolder(ViewHolder holder, int position) {holder.bind(onItemClickListener);}@Override public int getItemCount() {return 100;}public interface OnItemClickListener {void onItemClick(int position);}}
So i have created my own Runnable implementation to create CountdownTimer and created its instance inside ViewHolder to bind CountdownTimer with RecyclerView item. So now it will not flicker when we scroll RecyclerView. Thats why i created RecyclerView with 100 items in it, so we can check if there is any flickering or not.
Quick Links
Legal Stuff
Social Media