UPDATE
As pointed out by others in other posts, you should know when to start and stop the timer, because this creates problems. I managed to do this work without canceling the processor, so here is my code. Hope it helps. Any feedback is welcome.
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(); } }}
shadow-01
source share