欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android利用RecyclerView实现列表倒计时效果

程序员文章站 2022-05-31 15:32:02
最近面试时,面试官问了一个列表倒计时效果如何实现,然后脑袋突然懵的了O(∩_∩)O,现在记录一下。 运行效果图 实现思路 实现方法主要有两个: 1.为每个开始倒计时的item启动一个定时器,再做更新item处理; 2.只启动一个定时器,然后遍历数据,再做再做更新item处理。 经过思考,包括性能、实 ......

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

运行效果图

Android利用RecyclerView实现列表倒计时效果

实现思路

实现方法主要有两个:
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);
                }
            }
        }
    }
}

项目地址




如有问题,欢迎及时沟通。