美文网首页
只开一个线程实现RecyclerView的每个Item显示计时功

只开一个线程实现RecyclerView的每个Item显示计时功

作者: 猫小萌的哥哥 | 来源:发表于2018-04-09 00:36 被阅读491次

    当我看到这个需求的时候第一时间想的是在adapter中去开启线程去控制item

    上述方法带来的结果
    • 实践之后发现只有最后一个item的计时器在运行;
    • 我该在什么时候关闭线程,这也是个问题。

    于是,简单嘛!多开几个线程就搞定了啊【手动滑稽】

    • 应该开个线程池来管理,线程池的管理工具类还没有开始写,就发现问题了,我的item数量是几十上百的,到底要开多少线程?10个?20个?甚至是100个,管理起来及其复杂。我当时的心情是这样的:


    • 上网搜索了一波儿,发现有人跟我差不多的需求,而且已经实现功能了,大体是说在activity中开启线程管理所有的item参考了一波儿;简直恍然大悟,犹如醍醐灌顶啊,于是继续开始了我的操作。参考博客传送门

    开始我的操作

    1、开启一个一秒更新一次的线程

        private Handler mHandler;
        private TimeThread timeThread;
        private boolean isCloseThread = false;//是否关闭线程,默认为false
    
        /**
         * 定义一个跑时间的线程
         */
        class TimeThread extends Thread {
            @Override
            public void run() {
                do {
                    try {
                        Thread.sleep(1000);
                        Message msg = new Message();
                        msg.what = 1;  //消息(一个整型值)
                        mHandler.sendMessage(msg);// 每隔1秒发送一个msg给mHandler
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } while (!isCloseThread);
            }
        } 
    

    2、实例化TimeThrea和Handler,并更新数据让时间跑起来

        /**
         * 显示计时时间
         */
        private void setTimer() {
            isCloseThread = false;
            timeThread = new TimeThread();
            if (!timeThread.isAlive()) {
                timeThread.start();
            }
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == 1) {
                        for (int i = 0; i < usedParkSpaceAdapter.getData().size(); i++) {
                            if (usedParkSpaceAdapter.getData().get(i).getOrder() != null && isCloseThread == false) {
                                long startTime = usedParkSpaceAdapter.getData().get(i).getOrder().getParkStartTime();
                                String time = DateUtils.getCastToTime(startTime, (DateUtils.dateToLong(new Date()) / 1000));
                                try {
                                    BaseViewHolder holder = (BaseViewHolder) recyclerView.findViewHolderForAdapterPosition(i);
                                    holder.setText(R.id.park_used_time, time);
                                } catch (RuntimeException error) {
                                    Log.e(TAG, "handleMessage:"+error.getMessage());
                                }
                            }
                        }
                    }
                }
            };
        }
    
    **解释**:
    1.usedParkSpaceAdapter.getData().get(i);//拿到adapter中的数据;
    2.BaseViewHolder holder = (BaseViewHolder) recyclerView.findViewHolderForAdapterPosition(i);//获取当前item的位置;
    3.String time = DateUtils.getCastToTime(startTime, (DateUtils.dateToLong(new Date()) / 1000));//计算当前时间和开始时间的差并转化成 01:56:26 形式
    4.holder.setText(R.id.park_used_time, time);//将时间显示出来(这里adapter用的是[BaseRecyclerViewAdapterHelper](https://github.com/CymChad/BaseRecyclerViewAdapterHelper))
    
    这种方式只刷新了显示时间相关的控件,并不需要去做很复杂的操作来刷新数据,甚至都不需要 notifyDataSetChanged();
    
    

    3、adapter中的相关处理就很简单了,和平常没有差别,由于我的其他业务很多就不贴代码了。

    4、最后关闭线程

    @Override
        public void onDestroyView() {
            super.onDestroyView();
            unbinder.unbind();
            isCloseThread = true;//看这一句就行
        }
    

    结语:写代码之前先把思路整理清楚了,先做什么后做什么,能不能行的通,这样会少走些弯路。

    相关文章

      网友评论

          本文标题:只开一个线程实现RecyclerView的每个Item显示计时功

          本文链接:https://www.haomeiwen.com/subject/ylhvhftx.html