RecyclerView 倒计时和正计时方案

news2024/7/30 9:45:59

在这里插入图片描述

本章内容

  • 一.方案制定
  • 二.设计
  • 三.编码

相信不少同学都会在这里栽跟头,在思考这个问题设计了两套方案,而我的项目需求中需要根据业务是否反馈来进行倒计时和正计时的操作。

一.方案制定

1.在Adapter中使用CountDownTimer
2.修改数据源更新数据
3.只修改页面展示的Item

第一种方案:如果使用CountDownTimer来进行倒计时的话,会造成计时器时间错乱的问题。计时器会根据你更新UI的次数越走越快。
第二种方案:在数据量不大的情况下,是可以进行使用的。但是会存在资源浪费,这里会将没有显示到页面中的数据也会进行运算操作。
第三种方案:第二种方案比第二种方案设计上会更加节省资源,并且不会伴随第一种方案的及时错乱。

二.设计

  • 创建RecyclerView.Adapter

  • 需要在ViewHodler里面添加一个计时器组件,使用Handler就足够满足需求。我们需要在进入屏幕时,开启倒计时,在滑出屏幕后,停止计时器来节省CPU资源。

  • 需要注意的是:进入屏幕会触发Recycler.Adapter的onBindViewHolder()函数,滑出屏幕会触发onViewRecycled()

    有以上准备,我们就可以进入撸码环节了。

三.编码

主要工作都在与RecyclerView.Holder中。

public class ChatItemHolder extends BaseViewHolder {
        //用来判断是倒计时还是正计时
        public boolean isCountdown;
        //这个是我的业务逻辑,触发正反计时就看是否反馈信息
        public boolean isFeedback;
		//倒计时/正计时时间
        public long delay;
        //倒计时任务
        private Runnable countdownRunnable = new Runnable() {
            @Override
            public void run() {
                delay -= 1000;
                if (delay == 0) {
                    isCountdown = false;
                } else {
                    isCountdown = true;
                }
                updateTimerState();
            }
        };
        //正计时任务
        private Runnable positiveTimeRunnable = new Runnable() {
            @Override
            public void run() {
                delay += 1000;
                updateTimerState();
            }
        };
        //启动倒计时
        public void startCountdown() {
            timerHandler.postDelayed(countdownRunnable, 1000);
        }
        //结束倒计时
        public void endCountDown() {
            timerHandler.removeCallbacks(countdownRunnable);
        }
        //启动正计时
        public void startPositiveTime() {
            timerHandler.postDelayed(positiveTimeRunnable, 1000);
        }
        //结束正计时
        public void endPositiveTime() {
            timerHandler.removeCallbacks(positiveTimeRunnable);
        }

        //更新UI
        public void updateTimerState() {
            if (isFeedback) {  //如果已反馈关闭计时器
                endCountDown();
                endPositiveTime();
            } else {//进行计时并显示的格式为1天1时1分1秒
                long time = delay / 1000; //变成秒
                long temp = time % (24 * 3600);
                long day = time / (24 * 3600); //天
                long hour = temp / 3600; //小时
                long minute = temp % 3600 / 60; //分钟
                long second = temp % 60; //秒
                if (isCountdown) {
                    if (day == 0) {
                        setText(R.id.command_feedback_state, "反馈剩余时间:" + hour + "时" + minute + "分" + second + "秒");
                    } else {
                        setText(R.id.command_feedback_state, "反馈剩余时间:" + day + "天" + hour + "时" + minute + "分" + second + "秒");
                    }
                    setTextColor(R.id.command_feedback_state, Color.parseColor("#1890ff"));
                    setBackgroundResource(R.id.command_feedback_state,
                            R.drawable.shape_solid_null_stroke_1890ff_corner);
                    startCountdown();
                } else {
                    if (day == 0) {
                        setText(R.id.command_feedback_state, "超时时间:" + hour + "时" + minute + "分" + second + "秒");
                    } else {
                        setText(R.id.command_feedback_state, "超时时间:" + day + "天" + hour + "时" + minute + "分" + second + "秒");
                    }
                    setTextColor(R.id.command_feedback_state, Color.parseColor("#ff001b"));
                    setBackgroundResource(R.id.command_feedback_state,
                            R.drawable.shape_solid_null_stroke_ff001b);
                    startPositiveTime();
                }
            }
        }


        public void display(CommandChatBean.Data.Records record) {
            long time = DateUtil.ifsUtcStringToLocalForLong(record.getCzsx());
            delay = time - System.currentTimeMillis();
            isCountdown = delay > 0;
            isFeedback = !TextUtils.isEmpty(record.getCcFksj());
            delay = Math.abs(delay);
            updateTimerState();
        }

        public void onRecycled() {
            endCountDown();
            endPositiveTime();
        }

        public ChatItemHolder(View view) {
            super(view);
        }
    }
    //recyclerView内写入的方法:该方法是为了关闭页面后可以移除所有计时任务
    public void recycleTime() {
        if (timerHandler != null) {
            timerHandler.removeCallbacksAndMessages(null);
            timerHandler = null;
        }
    }

我这里使用的是封装好的AdapterHelper,可以直接集成RecyclerView.ViewHolder进行获取控件在进行更新。替换我下面的代码逻辑:

  setText(R.id.command_feedback_state, "超时时间:" + hour + "时" + minute + "分" + second + "秒");
                    } else {
                        setText(R.id.command_feedback_state, "超时时间:" + day + "天" + hour + "时" + minute + "分" + second + "秒");
                    }
                    setTextColor(R.id.command_feedback_state, Color.parseColor("#ff001b"));
                    setBackgroundResource(R.id.command_feedback_state,
                            R.drawable.shape_solid_null_stroke_ff001b);

RecyclerAdapter的onBindViewHolder(ChatItemHolder viewHolder,int position)中使用方式:

···
if (!TextUtils.isEmpty(records.getCzsx()) && TextUtils.isEmpty(records.getCcFksj())) {
                baseViewHolder.setVisible(R.id.command_feedback_state, true);
                baseViewHolder.display(records);
            }
            if (TextUtils.isEmpty(records.getCzsx())) {
                baseViewHolder.setVisible(R.id.command_feedback_state, false);
            }
            if (!TextUtils.isEmpty(records.getCcFksj())) {
                baseViewHolder.setVisible(R.id.command_feedback_state, true);
                baseViewHolder.setText(R.id.command_feedback_state,
                        "已反馈:" + DateUtil.ifsUtcStringToLocalForString(records.getCcFksj()));
                baseViewHolder.setTextColor(R.id.command_feedback_state, Color.parseColor("#4BBA55"));
                baseViewHolder.setBackgroundResource(R.id.command_feedback_state,
                        R.drawable.shape_solid_null_stroke_4bba55);
            }
···            

今天就分享到这里了,祝小伙伴新年快乐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode--各种数据结构相关的题

数据结构1.数组(1)找到所有数组中消失的数字(448)(2)旋转图像(48)(3)搜索二维矩阵 II(240)(4)最多能完成排序的块(769)2.栈和队列(1)用栈实现队列(232)&#…

“链引擎”(PBC)计划 | 太保集团长安链应用展示

引言 长安链“链引擎”计划(Powered by Chainmaker)(简称:PBC计划)是由长安链生态联盟发起的一项应用赋能计划,旨在以长安链技术体系为核心支撑,汇聚产业各方力量,为应用方提供技术、品牌、生态等支持&…

面试干货!初级软件测试面试题及答案题库一起奉上

软件测试工程师面试通常要经历技术面以及HR面,HR面一般都是日常问题,面试人可以临场发挥过去,但关乎岗位职责的技术面,可就没那么容易了,尤其是对于很多初次去面试测试岗位的没有任何测试岗位面试经验的转行人员&#…

Java并发面试题

基础知识 并发编程的优缺点 为什么要使用并发编程(并发编程的优点) 充分利用多核CPU的计算能力:通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升方便进行业务拆分,提升系统并发能力和性能&#…

【网络安全】内网介绍+windows信息收集(含命令)

目录 前言 一、内网渗透测试是什么? 1.介绍 2.内外网区别 3.工作组是什么? 4.域是什么? 5.域的知识点 6.活动目录 7.活动目录主要功能 8.域权限 二、windows信息收集 (1)系统信息 (2&#xff0…

【pandas】17 数据处理和绘图

【pandas】17 数据处理和绘图 2023.1.16 pandas数据处理方法和绘图:读取数据、更改数据、时间数据等 主要参考:https://mofanpy.com/tutorials/data-manipulation/pandas/time 17.1运算方法 17.1.1 筛选赋值运算 就是用前面的方法对数据进行筛选&#…

AI中Deepfake的部分研究前沿与文献综述

AI中Deepfake的部分研究前沿与文献综述一、研究现状二、典型算法:三、存在问题四、未来的研究热点参考文献:一、研究现状 由于Deepfake其潜在的安全威胁,它已经引起了学术界和工业界的研究兴趣。为了减轻这种风险,人们提出了许多…

【Nginx01】Ngnix入门

1.版本 Nginx开源版Nginx plus商业版OpenrestyTengine 2.Nginx开源版安装 2.1下载 2.2编译安装 如果本身没有c语言的编译器 命令: yum install -y gcc 解压Nginx 命令: tar -zxvf nginx-1.22.1.tar.gz 安装perl库 命令: yum install -y p…

广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”

文章目录广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”服务 Docker 构建及部署代码支持服务打包&构建服务部署广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署” 服务 Docker 构建及部署 在 ADX 系统中,全链路涉及 大大小小的微服务…

SpringBoot+VUE前后端分离项目学习笔记 - 【22 权限菜单 下】

本节主要实现用户角色菜单分配功能,并且实现前端的动态渲染以及动态路由 数据库: sys_user表增加role字段; sys_role增加flag字段;sys_menu表增加page_path字段。前两者表示用户角色标识,后者是前端页面vue路径,用以实现动态路由 …

verilog学习笔记- 13)呼吸灯实验

目录 简介: 实验任务: 硬件设计: 程序设计: 下载验证: 简介: 呼吸灯采用 PWM 的方式,在固定的频率下,通过调整占空比的方式来控制 LED 灯亮度的变化。PWM即脉冲宽度调制&#x…

2021年帆软杯一等奖作品 |《基于数据可视化的中国编程岗位需求分析》

# 作品主题 #——基于数据可视化的中国编程岗位需求分析一、团队介绍 团队名称:汪汪队立大功 团队成员:乔好鑫、许春阳、窦晨辉 指导老师:施金妹 团队的三位成员均是来自于海南科技职业大学大数据技术与应用专业,专业课主修了pyt…

SpringBoot+2次MD5登录密码加密+MyBatisPlus+Thymeleaf+Bootstrap简单实现登录功能,一文轻松搞定!

这里写目录标题一、演示GIF二、开发前期准备1、数据库2、依赖POM.XML3、idea结构目录三、后端1、实体类2、mapper接口3、mapper.xml4、Servicce接口5、Impl实现6、Controller控制器7、全局异常处理类GlobalExceptionGlobalExceptionHandler8、工具类MD5UtilUUIDUtilCookieUtilV…

消息批处理端口说明

为满足用户需要对多文件做批处理的需求,在2022版本的知行之桥中,开发人员开发设计了3个新的端口,分别是Batch Create 端口、Batch Merge 端口和Batch Split 端口。 功能是对传入端口的消息做批处理,使得消息可以在批处理组中分组在…

mybatis-plus分布式id重复问题

问题起因 k8s 部署的一个服务的两个节点集群 最近频繁报错,数据库主键ID重复,导致数据插入报错 问题定位 还在定位。。。。 问题解决 解决办法主要有两个 指定mybatis-plus workerId dataCenterId 全局配置 #注意这里使用的随机策略 随机区间 …

智能边缘网关

背景介绍 调研发现,数字经济为工业物联网、智能交通以及智慧医疗等场景提出了新的解决方案。工程师利用传感器边缘网关云服务器的系统架构,通过大数据及人工智能算法进行辅助决策,最终为工业设备赋能,提高加工生产效率。近年来&am…

sqli-labs 11~14 多命通关攻略(报错注入)

sqli-labs 11~14 多命通关攻略(报错注入)描述判断注入类型返回结果错误输入总结符号注释判断返回结果中的列数判断返回结果中的列数为 1判断返回结果中的列数为 2报错注入通过报错注入爆破数据库中的表名通过报错注入爆破数据库中的表名(逻辑…

【高阶数据结构】封装unordered_map 和 unordered_set

🌈欢迎来到数据结构专栏~~封装unordered_map 和 unordered_set (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞&…

【北京理工大学-Python 数据分析-3.1Pandas库的基本使用】

Pandas库的引用,常用两大功能Series(一维)和DataFrame(二维和多维) Pandas是Python第三方库,提供高性能易用数据类型的分析工具。 Pandas基于NumPy实现,常与NumPy和Matplotlib一起使用。 Numpy和Pandas的…

SpringCloud-Netflix学习笔记03——什么是Eureka

什么是Eureka Eureka:怎么读? Netflix 在设计Eureka 时,遵循的就是AP原则。 1、CAP原则又称CAP定理,指的是在一个分布式系统中 2、一致性(Consistency) 3、可用性(Availability) 4、…