当前位置: 移动技术网 > 移动技术>移动开发>Android > Android如何利用RecyclerView实现列表倒计时效果实例代码

Android如何利用RecyclerView实现列表倒计时效果实例代码

2019年07月29日  | 移动技术网移动技术  | 我要评论

前言

最近面试时,面试官问了一个列表倒计时效果如何实现,然后脑袋突然懵的了o(∩_∩)o,现在记录一下。

运行效果图

实现思路

实现方法主要有两个:

1.为每个开始倒计时的item启动一个定时器,再做更新item处理;

2.只启动一个定时器,然后遍历数据,再做再做更新item处理。

经过思考,包括性能、实现等方面,决定使用第2种方式实现。

实现过程

数据实体

/** 
 * 总共的倒计时的时间(结束时间-开始时间),单位:毫秒 
 * 例: 2019-02-23 11:00:30 与 2019-02-23 11:00:00 之间的相差的毫秒数 
 */ 
 private long totaltime; 
 /** 
 * 倒计时是否在暂停状态 
 */ 
 private boolean ispause = true; 

倒计时

timer

mtimer.schedule(mtask, 0, 1000);

timertask

 class mytask extends timertask {
  @override
  public void run() {
   if (mlist.isempty()) {
    return;
   }
   int size = mlist.size();
   countdowntimerbean bean;
   long totaltime;
   for (int i = 0; i < size; i++) {
    bean = mlist.get(i);
    if (!bean.ispause()) {//不处于暂停状态
     totaltime = bean.gettotaltime() - 1000;
     if (totaltime <= 0) {
      bean.setpause(true);
      bean.settotaltime(0);
     }
     bean.settotaltime(totaltime);
     message message = mhandler.obtainmessage(1);
     message.arg1 = i;
     mhandler.sendmessage(message);
    }
   }
  }
 }

线程交互更新item

 mhandler = new handler(looper.getmainlooper()) {
   @override
   public void handlemessage(message msg) {
    switch (msg.what) {
     case 1:
      notifyitemchanged(msg.arg1, "update-time");
      break;
    }
   }
  };

性能优化方面

1.调用notifyitemchanged()方法后,不要更新整个item(比如说item包含图片,不需要变的),所以要重写onbindviewholder( holder , int , list

@override
 public void onbindviewholder(@nonnull holder holder, int position, @nonnull list<object> payloads) {
  if (payloads.isempty()) {
   onbindviewholder(holder, position);
   return;
  }
  //更新某个控件,比如说只需要更新时间信息,其他不用动
  countdowntimerbean bean = mlist.get(position);
  long day = bean.gettotaltime() / (1000 * 60 * 60 * 24);
  long hour = (bean.gettotaltime() / (1000 * 60 * 60) - day * 24);
  long min = ((bean.gettotaltime() / (60 * 1000)) - day * 24 * 60 - hour * 60);
  long s = (bean.gettotaltime() / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
  holder.tvtime.settext("剩余时间: " + day + "天" + hour + "小时" + min + "分" + s + "秒");
  holder.btnaction.settext(bean.ispause() ? "开始" : "暂停");
  holder.btnaction.setenabled(bean.gettotaltime() != 0);
 }

2.销毁资源操作:

 /**
  * 销毁资源
  */
 public void destroy() {
  mhandler.removemessages(1);
  if (mtimer != null) {
   mtimer.cancel();
   mtimer.purge();
   mtimer = null;
  }
 }

recyclerview.adapter部分源码

public class countdowntimeradapter extends recyclerview.adapter<countdowntimeradapter.holder> {
 private static final string tag = "countdowntimeradapter->";
 private list<countdowntimerbean> mlist;//数据
 private handler mhandler;//线程调度,用来更新列表

 private timer mtimer;
 private mytask mtask;

 public countdowntimeradapter() {
  mlist = new arraylist<>();
  mhandler = new handler(looper.getmainlooper()) {
   @override
   public void handlemessage(message msg) {
    switch (msg.what) {
     case 1:
      notifyitemchanged(msg.arg1, "update-time");
      break;
    }
   }
  };
  mtask = new mytask();
 }

 public void bindadaptertorecyclerview(@nonnull recyclerview view) {
  view.setadapter(this);
 }

 /**
  * 设置新的数据源
  *
  * @param list 数据
  */
 public void setnewdata(@nonnull list<countdowntimerbean> list) {
  destroy();
  mlist.clear();
  mlist.addall(list);
  notifydatasetchanged();
  if (mtimer == null) {
   mtimer = new timer();
  }
  mtimer.schedule(mtask, 0, 1000);
 }

 /**
  * 销毁资源
  */
 public void destroy() {
  mhandler.removemessages(1);
  if (mtimer != null) {
   mtimer.cancel();
   mtimer.purge();
   mtimer = null;
  }
 }

 @nonnull
 @override
 public holder oncreateviewholder(@nonnull viewgroup viewgroup, int i) {
  view view = layoutinflater.from(viewgroup.getcontext()).inflate(r.layout.item_count_down_timer, viewgroup, false);
  return new holder(view);
 }

 @override
 public void onbindviewholder(@nonnull holder holder, int position, @nonnull list<object> payloads) {
  if (payloads.isempty()) {
   onbindviewholder(holder, position);
   return;
  }
  //更新某个控件,比如说只需要更新时间信息,其他不用动
  countdowntimerbean bean = mlist.get(position);
  long day = bean.gettotaltime() / (1000 * 60 * 60 * 24);
  long hour = (bean.gettotaltime() / (1000 * 60 * 60) - day * 24);
  long min = ((bean.gettotaltime() / (60 * 1000)) - day * 24 * 60 - hour * 60);
  long s = (bean.gettotaltime() / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
  holder.tvtime.settext("剩余时间: " + day + "天" + hour + "小时" + min + "分" + s + "秒");
  holder.btnaction.settext(bean.ispause() ? "开始" : "暂停");
  holder.btnaction.setenabled(bean.gettotaltime() != 0);
 }

 @override
 public void onbindviewholder(@nonnull final holder holder, int position) {
  holder.ivicon.setimageresource(r.mipmap.ic_launcher_round);
  final countdowntimerbean bean = mlist.get(position);
  long day = bean.gettotaltime() / (1000 * 60 * 60 * 24);
  long hour = (bean.gettotaltime() / (1000 * 60 * 60) - day * 24);
  long min = ((bean.gettotaltime() / (60 * 1000)) - day * 24 * 60 - hour * 60);
  long s = (bean.gettotaltime() / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
  holder.tvtime.settext("剩余时间: " + day + "天" + hour + "小时" + min + "分" + s + "秒");
  holder.btnaction.settext(bean.ispause() ? "开始" : "暂停");
  holder.btnaction.setenabled(bean.gettotaltime() != 0);
  holder.btnaction.setonclicklistener(new view.onclicklistener() {
   @override
   public void onclick(view v) {
    if (bean.ispause()) {
     bean.setpause(false);
     holder.btnaction.settext("暂停");
    } else {
     bean.setpause(true);
     holder.btnaction.settext("开始");
    }
   }
  });
 }

 @override
 public int getitemcount() {
  return mlist.size();
 }

 class holder extends recyclerview.viewholder {
  private imageview ivicon;
  private textview tvtime;
  private button btnaction;

  holder(@nonnull view itemview) {
   super(itemview);
   ivicon = itemview.findviewbyid(r.id.iv_icon);
   tvtime = itemview.findviewbyid(r.id.tv_time);
   btnaction = itemview.findviewbyid(r.id.btn_action);
  }
 }

 class mytask extends timertask {
  @override
  public void run() {
   if (mlist.isempty()) {
    return;
   }
   int size = mlist.size();
   countdowntimerbean bean;
   long totaltime;
   for (int i = 0; i < size; i++) {
    bean = mlist.get(i);
    if (!bean.ispause()) {//不处于暂停状态
     totaltime = bean.gettotaltime() - 1000;
     if (totaltime <= 0) {
      bean.setpause(true);
      bean.settotaltime(0);
     }
     bean.settotaltime(totaltime);
     message message = mhandler.obtainmessage(1);
     message.arg1 = i;
     mhandler.sendmessage(message);
    }
   }
  }
 }
}

项目地址

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网