I am making some kind of Sale event app . For that i require a Recyclerview with each item having a countdown timer in it. Each items has countdown and it says "Sale begins in XX hr: YY min" And when the countdown of the item expires , the item should go down to the bottom of Recyclerview.
I have made a countdown timer inside onbindviewholder but i am getting error when the timer expires . Please someone help me overcome this... This is what is required img
The expiry time of each item is coming from Firestore database .
I am doing this in my onbindViewholder... String remTime;
@Override
public void onBindViewHolder(@NonNull Holder holder, int position) {
ItemDet item = ItemArrayList.get(position);
long timer = item.getCategoryTime().toDate().getTime();
final long currentTime = System.currentTimeMillis();
long expiryTime = timer - currentTime;
if (holder.timer != null) {
holder.timer.cancel();
}
holder.timer=new CountDownTimer(expiryTime, 1000) {
public void onTick(long millisUntilFinished) {
long seconds = millisUntilFinished / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
if(days==0){
remTime= minutes % 60 "m:" seconds % 60 "s";
}
if(days<1 && hours>0 && minutes>0 && seconds>0){
remTime= hours % 24 "h:" minutes % 60 "m";
}
if(days<1 && hours<1 && minutes>0 && seconds>0){
remTime= minutes % 60 "m:" seconds % 60 "s";
}
if(days<1 && hours<1 && minutes<1 && seconds>0){
remTime= seconds % 60 "s";
}
if (days>0){
remTime= days "d, " hours % 24 "h";
}
holder.item_time_h.setText(remTime);
}
public void onFinish() {
holder.itemView.setEnabled(false);
holder.item_time_h.setText("Time up!");
ItemArrayList.remove(holder.adapterPosition());
notifyItemRemoved(holder.adapterPosition());
notifyItemRangeChanged(holder.adapterPosition(), ItemArrayList.size());
//Here after timer finish i want to remove the item from the top and put it on bottom
}
Please help me in this, i am stuck since 2 weeks
CodePudding user response:
This shouldn't be hard. When the timer ends, you should move the item to the end of the list and then notify the adapter about this.
public void onFinish() {
holder.itemView.setEnabled(false);
holder.item_time_h.setText("Time up!");
int oldPosition = holder.adapterPosition();
ItemDet item = ItemArrayList.remove(oldPosition);
ItemArrayList.add(item);
int newPosition = ItemArrayList.size() - 1;
notifyItemMoved(oldPosition, newPosition);
}
Hope I didn't make mistakes. I didn't test the code. Try this. I'm hoping for some feedback from you.
UPDATE
Now I see that your expiryTime
depends on the System's time and it's not a fixed value. As the time passes, some of your Counters will finish counting. In that exact moment when the Counter finishes to count, if you would recompute expiryTime
, its value will be 0
. When you exit the fragment and reenter it, the fragment will get recreated, the recyclerview will get recreated and the expiryTime
will get recomputed and it will be a negative value. And because of that the Counter's onFinish
method will be called right away, when the recycler's layout is being created. A quick fix could be that to not start the timer if expiryTime
is negative. For the moment I think you could do this:
final long currentTime = System.currentTimeMillis();
long expiryTime = timer - currentTime;
//ADD THIS HERE
if(expiryTime <= 0) {
return;
}
if (holder.timer != null) {
holder.timer.cancel();
}