Recyclerview with multiple countdown timers causes flickering

H Raval picture H Raval · Mar 8, 2016 · Viewed 8.1k times · Source

I want to show how much time is left inside each cell of my RecyclerView...for that I have used a countdown timer for each. In each row I start a counter and manage onTick()...all works as expected...I've got a timer tick for each row and my cell is also updating but my cell is flickering now....and it goes crazy when I scroll.

Here is my adapter...

if (product.getProductType().equalsIgnoreCase("Auction Product")) {
                isAuction=true;
                viewHolder.img_product_type.setImageResource(R.drawable.bid);
                viewHolder.txt_timeleft.setVisibility(View.VISIBLE);
               start_countDown(product.getStart(),product.getStop(),viewHolder.txt_timeleft);
            }

counter code is as below....

private void start_countDown(String start, String stop, final TextView txt_timeleft) {
        try {
            //Log.e("hetal",start+"....."+stop);
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            Calendar start_date = Calendar.getInstance();
            start_date.setTime(format.parse(start));

            Calendar end_date = Calendar.getInstance();
            end_date.setTime(format.parse(stop));

            final Calendar today = Calendar.getInstance();
            CountDownTimer timer;

            txt_timeleft.setTextColor(Color.DKGRAY);
            if(today.before(start_date)){
                txt_timeleft.setTextColor(context.getResources().getColor(R.color.red));
                txt_timeleft.setText(context.getString(R.string.auction_not_start));
                Animation anim = new AlphaAnimation(0.0f, 1.0f);
                anim.setDuration(1000); //You can manage the time of the blink with this parameter
                anim.setStartOffset(20);
                anim.setRepeatMode(Animation.REVERSE);
                anim.setRepeatCount(Animation.INFINITE);
                txt_timeleft.startAnimation(anim);
                return;
            }
            if (!today.before(end_date)) {

                txt_timeleft.setTextColor(context.getResources().getColor(R.color.red));
                txt_timeleft.setText(context.getString(R.string.time_out));
                        Animation anim = new AlphaAnimation(0.0f, 1.0f);
                        anim.setDuration(1000); //You can manage the time of the blink with this parameter
                        anim.setStartOffset(20);
                        anim.setRepeatMode(Animation.REVERSE);
                        anim.setRepeatCount(Animation.INFINITE);
                txt_timeleft.startAnimation(anim);
                return;
            }

            timer = new CountDownTimer(end_date.getTimeInMillis(), 1000) {
                @Override
                public void onTick(long millisUntilFinished) {

                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(millisUntilFinished);

                    long diff = calendar.getTimeInMillis() - today.getTimeInMillis();

                    long seconds = diff / 1000 % 60;
                    long minutes = diff / (60 * 1000) % 60;
                    long hours = diff / (60 * 60 * 1000) % 24;
                    //long days = (int) diff / (24 * 60 * 60 * 1000);
                    long days = TimeUnit.MILLISECONDS.toDays(diff);


                    String left = "";
                    if (days > 0)
                        left += days + " " + context.getString(R.string.txt_day) + " ,";
                    if (hours > 0)
                        left += hours + " " + context.getString(R.string.txt_hour) + " ,";
                    if (minutes > 0)
                        left += minutes + " " + context.getString(R.string.txt_minute) + " ,";

                    left += seconds + " " + context.getString(R.string.txt_second);

                    final String finalLeft = left;


                            if (finalLeft.equals("0") || finalLeft.contains("-")) {
                                txt_timeleft.setText(context.getString(R.string.time_out));
                                txt_timeleft.setTextColor(context.getResources().getColor(R.color.red));
                                Animation anim = new AlphaAnimation(0.0f, 1.0f);
                                anim.setDuration(1000); //You can manage the time of the blink with this parameter
                                anim.setStartOffset(20);
                                anim.setRepeatMode(Animation.REVERSE);
                                anim.setRepeatCount(Animation.INFINITE);
                                txt_timeleft.startAnimation(anim);
                            } else
                                txt_timeleft.setText(finalLeft);
                }

                @Override
                public void onFinish() {

                }
            };
            timer.start();
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

Answer

H Raval picture H Raval · Mar 8, 2016

thanx Hammad Tariq Sahi i have used your logic and solve my problem in this way....i have also refereed this link

in my adapter

ArrayList<ViewHolder> viewHoldersList;
    private Handler handler = new Handler();
    private Runnable updateRemainingTimeRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (viewHoldersList) {
                for (ViewHolder holder : viewHoldersList) {
                    holder.updateTimeRemaining();
                }
            }
        }
    };

inside constructor of my adapter

viewHoldersList = new ArrayList<>();
startUpdateTimer();

and added this method to calculate time

private void startUpdateTimer() {
        Timer tmr = new Timer();
        tmr.schedule(new TimerTask() {
            @Override
            public void run() {
                handler.post(updateRemainingTimeRunnable);
            }
        }, 1000, 1000);
    }

added two methods to my viewholder class

public void setData(Product product){
            this.product = product;
        }
        public void updateTimeRemaining() {
            if(product.getProductType().equalsIgnoreCase("Auction Product")) {
                Log.e("hetal",product.getProductType());
                try {
                    String start = product.getStart();
                    String stop = product.getStop();

                    //txt_timeleft.setText("");
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                    Calendar start_date = Calendar.getInstance();
                    start_date.setTime(format.parse(start));

                    Calendar end_date = Calendar.getInstance();
                    end_date.setTime(format.parse(stop));

                    final Calendar today = Calendar.getInstance();
                    CountDownTimer timer;

                    long timeDiff = end_date.getTimeInMillis() - today.getTimeInMillis();
                    if (timeDiff > 0) {
                        long seconds = timeDiff / 1000 % 60;
                        long minutes = timeDiff / (60 * 1000) % 60;
                        long hours = timeDiff / (60 * 60 * 1000) % 24;
                        //long days = (int) diff / (24 * 60 * 60 * 1000);
                        long days = TimeUnit.MILLISECONDS.toDays(timeDiff);


                        String left = "";
                        if (days > 0)
                            left += days + " " + context.getString(R.string.txt_day) + " ,";
                        if (hours > 0)
                            left += hours + " " + context.getString(R.string.txt_hour) + " ,";
                        if (minutes > 0)
                            left += minutes + " " + context.getString(R.string.txt_minute) + " ,";

                        left += seconds + " " + context.getString(R.string.txt_second);

                        final String finalLeft = left;
                        txt_timeleft.setText(finalLeft);
                    } else {
                        txt_timeleft.setText("Time Out !!");
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }

and finally inside onBindViewHolder

synchronized (viewHoldersList) {
                viewHolder.setData(product);
                if(viewHoldersList.size()< (list.size()-2)) viewHoldersList.add(viewHolder);
            }

works perfect....thanx all