UPDATE
As stated by others in other posts you have to know when to start and stop the timer because this is making you problems.
I manged to make this work without canceling the recycler so here is my code.
public class ViewHolderContentCard extends RecyclerView.ViewHolder {
public TextView cardTv;
public CountdownUtils countdownUtils;
public ViewHolderContentCard(final View itemView) {
super(itemView);
cardTv = (TextView) itemView.findViewById(R.id.cardCountDownTvID);
countdownUtils = new CountdownUtils(cardTv);
}}
public class ContentRecyclerAdapterCard extends RecyclerView.Adapter<ViewHolderContentCard> {
private ArrayList<Content> mContentArrayList;
public ContentRecyclerAdapterCard(ArrayList<Content> contentArrayList) {
this.mContentArrayList = contentArrayList;
}
@Override
public ViewHolderContentCard onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_content, parent, false);
ViewHolderContentCard viewHolderContentCard = new ViewHolderContentCard(view);
return viewHolderContentCard;
}
@Override
public void onBindViewHolder(ViewHolderContentCard holder, int position) {
holder.cardTextTv.setText(mContentArrayList.get(position).getmTitle());
//update count down
holder.countdownUtils.updateCountdownTv(mContentArrayList.get(position));
}
@Override
public int getItemCount() {
return mContentArrayList.size();
}}
public class CountdownUtils {
private TextView mTextView;
private CountDownTimer mTimer;
public CountdownUtils(TextView textView) {
mTextView = textView;
}
public void updateCountdownTv(Content content) {
//cancel old timer to make sure one timer is updating one card
cleanUpTimer();
//get beginning and expiration period
String dateFrom = content.getmDateFrom();
String dateTo = content.getmDateTo();
String timeFrom = content.getmTimeFrom();
String timeTo = content.getmTimeTo();
//process dates and update the countdown
processCountDownAndUpdateUI(mTextView, dateFrom, dateTo, timeFrom, timeTo);
}
private void processCountDownAndUpdateUI(final TextView textView, String dateFrom, String dateTo, String timeFrom, String timeTo) {
try {
//format date and time
Date beginningPeriod = getDateFromString(dateFrom, timeFrom);
Date expirationPeriod = getDateFromString(dateTo, timeTo);
//check beginning period with current time
if (System.currentTimeMillis() < beginningPeriod.getTime()) {
//we know that the is not available yet so display staring period - update the UI
textView.setText("Starting from: " + dateFrom + " " + timeFrom);
} else if (expirationPeriod.getTime() > System.currentTimeMillis()) {
long availabilityPeriod = getAvailabilityPeriod(expirationPeriod);
if (availabilityPeriod != 0) {
//we have a valid avilability period so we need to start the countdown - update the UI
startCountDownTimer(textView, availabilityPeriod);
}
}
} catch (ParseException e) {
e.printStackTrace();
}
}
private void startCountDownTimer(final TextView textView, long availabilityPeriod) {
//create countdown timer, count each second
mTimer = new CountDownTimer(availabilityPeriod, 1000) {
@Override
public void onTick(long millisUntilFinished) {
//format string will be displayed
String timeSting = String.format("%d days %02d:%02d:%02d",
TimeUnit.MILLISECONDS.toDays(millisUntilFinished),
TimeUnit.MILLISECONDS.toHours(millisUntilFinished) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(millisUntilFinished)),
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)),
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)));
//display countdown
textView.setText(timeSting);
}
@Override
public void onFinish() {
//expired inform the user
textView.setText("Expired");
}
}.start();
}
private long getAvailabilityPeriod(Date periodFrom) {
long availabilityPeriod = 0;
//get expiration date as long
long expPeriod = periodFrom.getTime();
//check availability period
if (expPeriod > System.currentTimeMillis()) {
availabilityPeriod = expPeriod - System.currentTimeMillis();
}
return availabilityPeriod;
}
private Date getDateFromString(String date, String time) throws ParseException {
//extract data as date and time
Date formattedDate = new SimpleDateFormat("yyyy/MM/dd HH:mm").parse(date + " " + time);
return formattedDate;
}
public void cleanUpTimer() {
if (mTimer != null){
mTimer.cancel();
} }}