I have two tab in my fragment.In my recyclerview there are two viewtypes, those two viewtype populates on depending of press in chips.On create view it works fine. But when I come back from the second viewtype the my countDown timer in the first viewtype flickers a bit. It shows a one number then changes to another.
long timeUntilStart = startDate.getTime() - currentTime.getTime();
long timeUntilEnd = endDate.getTime() - currentTime.getTime();
if (timeUntilStart > 0) {
CountDownTimer timer = new CountDownTimer(timeUntilStart, 1000) {
public void onTick(long millisUntilFinished) {
// Update the countdown timer text
long seconds = (millisUntilFinished / 1000) % 60;
long minutes = (millisUntilFinished / (1000 * 60)) % 60;
long hours = (millisUntilFinished / (1000 * 60 * 60));
((ExamListV2ActiveItemViewHolder) holder).binding.tvRemainingTime.setText(String.format("%02d Hour: %02d min :%02d sec", hours, minutes, seconds));
}
public void onFinish() {
((ExamListV2ActiveItemViewHolder) holder).binding.btnJoin.setVisibility(View.VISIBLE);
((ExamListV2ActiveItemViewHolder) holder).binding.tvStarts.setText(context.getResources().getString(R.string.exam_starts_in));
((ExamListV2ActiveItemViewHolder) holder).binding.btnJoin.setVisibility(View.VISIBLE);
CountDownTimer timer = new CountDownTimer(timeUntilEnd, 1000) {
public void onTick(long millisUntilFinished) {
// Update the countdown timer text
long seconds = (millisUntilFinished / 1000) % 60;
long minutes = (millisUntilFinished / (1000 * 60)) % 60;
long hours = (millisUntilFinished / (1000 * 60 * 60));
((ExamListV2ActiveItemViewHolder) holder).binding.tvRemainingTime.setText(String.format("%02d Hour %02d Min %02d Sec", hours, minutes, seconds));
}
public void onFinish() {
((ExamListV2ActiveItemViewHolder) holder).binding.tvRemainingTime.setText(context.getResources().getString(R.string.exam_ended));
}
};
timer.start();
}
};
timer.start();
here is my code. can anyone point out what i can do to avoid this
You should probably move the CountDownTimer
logic inside the holder itself and make sure to react on onViewRecycled
otherwise you creating one CountDownTimer for 2 holders and i guess they interfere each other
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
super.onViewRecycled(holder);
((ExamListV2ActiveItemViewHolder) holder).startTimer(startDate, endDate);
}
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
super.onViewRecycled(holder);
((ExamListV2ActiveItemViewHolder) holder).resetTimer();
}
Your holder would be like:
class ExamListV2ActiveItemViewHolder extends RecyclerView.ViewHolder {
CountDownTimer timer;
public ExamListV2ActiveItemViewHolder(@NonNull View itemView) {
super(itemView);
}
public void startTimer(final Date startDate, final Date endDate) {
final Date currentTime = new Date();
final long timeUntilStart = startDate.getTime() - currentTime.getTime();
final long timeUntilEnd = endDate.getTime() - currentTime.getTime();
if (timeUntilStart > 0) {
timer = new CountDownTimer(timeUntilStart, 1000) {
public void onTick(long millisUntilFinished) {
setCountDownTime(millisUntilFinished);
}
public void onFinish() {
binding.btnJoin.setVisibility(View.VISIBLE);
binding.tvStarts.setText(itemView.getContext().getResources().getString(R.string.exam_starts_in));
binding.btnJoin.setVisibility(View.VISIBLE);
timer = new CountDownTimer(timeUntilEnd, 1000) {
public void onTick(long millisUntilFinished) {
setCountDownTime(millisUntilFinished);
}
public void onFinish() {
binding.tvRemainingTime.setText(itemView.getContext().getResources().getString(R.string.exam_ended));
}
};
timer.start();
}
};
timer.start();
}
}
public void resetTimer() {
if (timer != null) timer.cancel();
}
private void setCountDownTime(long time) {
long seconds = (time / 1000) % 60;
long minutes = (time / (1000 * 60)) % 60;
long hours = (time / (1000 * 60 * 60));
binding.tvRemainingTime.setText(String.format("%02d Hour: %02d min :%02d sec", hours, minutes, seconds));
}
}