2

CountDownTimer is not showing while scrolling

Below is my code;

public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
{

   if (holder.timer != null) {
        holder.timer.cancel();
    }



  if (!resturantDetails.getRemainingTime().equalsIgnoreCase("") && holder.timer == null) {

            Log.e("AAAAAAAAAAAAAAAAAAAAAAAAA", "" + resturantDetails.getRemainingTime());
            holder.timer = new CountDownTimer(Long.parseLong(resturantDetails.getRemainingTime()), 1000) {
                @Override
                public void onTick(long millisUntilFinished) {

                    long seconds = (millisUntilFinished / 1000) % 60;
                    long minutes = ((millisUntilFinished / (1000 * 60)) % 60);
                    long hours = ((millisUntilFinished / (1000 * 60 * 60)) % 24);

                    holder.tvHour.setText(String.format("%02d", hours));
                    holder.tvMinutes.setText(String.format("%02d", minutes));
                    holder.tvSeconds.setText(String.format("%02d", seconds));
                }

                @Override

                public void onFinish() {

                }
            }.start();
        } 
}

Below is my ViewHolder class;

  public class ResturantDashboardViewHolder extends RecyclerView.ViewHolder {


        CountDownTimer timer;

        public ResturantDashboardViewHolder(View itemView) {
            super(itemView);

        }
    }
Vishal Vaishnav
  • 3,346
  • 3
  • 26
  • 57

2 Answers2

1

This problem is simple.

RecyclerView reuses the holders, calling bind each time to update the data in them.

Since you create a CountDownTimer each time any data is bound, you will end up with multiple timers updating the same ViewHolder.

The best thing here would be to cancel it before binding the data (if started) and rescheduling to the desired duration.

public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
    ...
    if (holder.timer != null) {
        holder.timer.cancel();
    }
    holder.timer = new CountDownTimer(expiryTime, 500) {
        ...
    }.start();
}

public static class ResturantDashboardViewHolder extends RecyclerView.ViewHolder {
    ...
    CountDownTimer timer;

    public FeedViewHolder(View itemView) {
        ...
    }
}

This way you will cancel any current timer instance for that ViewHolder prior to starting another timer.

Hanzala
  • 1,965
  • 1
  • 16
  • 43
0

Finally I got best solution;

Below is adapter code for count down timer

    public class RestaurantListDetailAdapter extends RecyclerView.Adapter<RestaurantListDetailAdapter.ResturantDashboardViewHolder> implements Filterable {

    ArrayList<RestaurantListDetail.DataModel.ResultList> resturantList = new ArrayList<>();
    Context mContext;
    Utils utils;
    String latitude, longitude;
    OffersAdapter offersAdapter;
    private ArrayList<RestaurantListDetail.DataModel.ResultList> mFilteredList;

    public RestaurantListDetailAdapter(ArrayList res, Context mContext, String latitude, String longitude) {
        this.resturantList = res;
        this.mContext = mContext;
        this.latitude = latitude;
        this.longitude = longitude;

        long maxTime = 0;
        for (RestaurantListDetail.DataModel.ResultList item : resturantList) {
            if (!item.getRemainingTime().equalsIgnoreCase("")) {
                maxTime = Long.parseLong(item.getRemainingTime());
            }
        }

        new CountDownTimer(maxTime, 1000) {
            @Override
            public void onTick(long l) {

                for (int i = 0, dataLength = resturantList.size(); i < dataLength; i++) {
                    RestaurantListDetail.DataModel.ResultList item = resturantList.get(i);
                    if (!item.getRemainingTime().equalsIgnoreCase("")) {
                        item.setRemainingTime(String.valueOf(Long.parseLong(item.getRemainingTime())-1000)) ;
                    }
                }

                //remove the expired items
                //Iterator<RestaurantListDetail.DataModel.ResultList> dataIterator = resturantList.iterator();
                //while (dataIterator.hasNext()) {
                //RestaurantListDetail.DataModel.ResultList rd = dataIterator.next();
                //if (rd.getRemainingTime().equalsIgnoreCase("")) {
                //          dataIterator.remove();
                //                        }
                //                    }
                notifyDataSetChanged();
            }

            @Override
            public void onFinish() {
            // resturantList.clear();
            // notifyDataSetChanged();
            }
        }.start();

    }

    @Override
    public ResturantDashboardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.dashboard_search_item, parent, false);
        ResturantDashboardViewHolder viewHolder = new ResturantDashboardViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final ResturantDashboardViewHolder holder, final int position) {
        final RestaurantListDetail.DataModel.ResultList resturantDetails = resturantList.get(position);

        if (!resturantDetails.getRemainingTime().equalsIgnoreCase(""))
        {
            long seconds = Long.parseLong(resturantDetails.getRemainingTime()) / 1000;
            long minutes = seconds / 60;

            holder.tvHour   .setText(String.format("%02d", TimeUnit.MILLISECONDS.toHours(Long.parseLong(resturantDetails.getRemainingTime()))));
            holder.tvMinutes.setText(String.format("%02d",minutes % 60));
            holder.tvSeconds.setText(String.format("%02d",seconds % 60));
        }

    }

    @Override
    public int getItemCount() {
        return resturantList.size();
    }


    public class ResturantDashboardViewHolder extends RecyclerView.ViewHolder {


        LinearLayout llBookingTable, ll_timer_slot, llOfferLayout, llOffers, rl_offer;
        TextView tv_resturantname, tvSeatLeft, tvListsTags, tvOffers, textView, tvHour, tvMinutes, tvSeconds, tvOutlets, tv_distance, tv_place, tv_rating, tvClosed, tvCostForTwo, tvOffer, tvSuburb;


        public ResturantDashboardViewHolder(View itemView) {
            super(itemView);

            tvOffers = itemView.findViewById(R.id.tvOffers);
            rl_offer = itemView.findViewById(R.id.rl_offer);
            tvSeatLeft = itemView.findViewById(R.id.tvSeatLeft);
            tvListsTags = itemView.findViewById(R.id.tvListsTags);
            textView = itemView.findViewById(R.id.textView);
            llOfferLayout = itemView.findViewById(R.id.llOfferLayout);

            llBookingTable = itemView.findViewById(R.id.llBookingTable);
            ll_timer_slot = itemView.findViewById(R.id.ll_timer_slot);
            tvHour = itemView.findViewById(R.id.tvHour);
            tvMinutes = itemView.findViewById(R.id.tvMinutes);
            tvSeconds = itemView.findViewById(R.id.tvSeconds);
            tvOutlets = itemView.findViewById(R.id.tvOutlets);
            llOffers = itemView.findViewById(R.id.llOffers);
            tvSuburb = itemView.findViewById(R.id.tvSuburb);
            tv_distance = itemView.findViewById(R.id.tv_distance);
            tv_place = itemView.findViewById(R.id.tv_resturant_place);
            tv_resturantname = itemView.findViewById(R.id.tv_resturant_item);
            tv_rating = itemView.findViewById(R.id.tv_rating);
            tvClosed = itemView.findViewById(R.id.tvClosed);
            tvCostForTwo = itemView.findViewById(R.id.tvCostForTwo);
            tvOffer = itemView.findViewById(R.id.tvOffer);
        }
    }

}
Vishal Vaishnav
  • 3,346
  • 3
  • 26
  • 57