最近在做一个项目,需要用到列表倒计时功能,捣鼓半天终于弄了出来,在安卓中实现这个效果需要用到Countdowntimer,通过这个类的使用,不仅可以实现倒计时的效果,还可以完美解决在实现倒计时过程中的两个bug。

1.内存问题

2.由于recyclerview的item复用导致不同条目的时间错乱

首先看下实现的最终效果

如何显示列表我相信大家都会,这里我只附上和倒计时功能实现的adapter类。

public class ClockAdapter extends RecyclerView.Adapter {

private SparseArray countDownMap = new SparseArray<>();

@Override

public ClockViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rv, parent, false);

return new ClockViewHolder(view);

}

/**

* 清空资源

*/

public void cancelAllTimers() {

if (countDownMap == null) {

return;

}

for (int i = 0,length = countDownMap.size(); i < length; i++) {

CountDownTimer cdt = countDownMap.get(countDownMap.keyAt(i));

if (cdt != null) {

cdt.cancel();

}

}

}

@Override

public void onBindViewHolder(final ClockViewHolder holder, int position) {

long betweenDate;

if (position == 0) {

betweenDate= DateUtil.getLeftTime("2017-8-8 12:10:10");

} else {

betweenDate= DateUtil.getLeftTime("2017-8-9 15:10:10");

}

if (holder.countDownTimer != null) {

holder.countDownTimer.cancel();

}

if (betweenDate > 0) {

holder.countDownTimer = new CountDownTimer(betweenDate, 1000) {

public void onTick(long millisUntilFinished) {

millisUntilFinished = millisUntilFinished / 1000;

int hours = (int) (millisUntilFinished / (60 * 60));

int leftSeconds = (int) (millisUntilFinished % (60 * 60));

int minutes = leftSeconds / 60;

int seconds = leftSeconds % 60;

final StringBuffer sBuffer = new StringBuffer();

sBuffer.append(addZeroPrefix(hours));

sBuffer.append(":");

sBuffer.append(addZeroPrefix(minutes));

sBuffer.append(":");

sBuffer.append(addZeroPrefix(seconds));

holder.clock.setText(sBuffer.toString());

}

public void onFinish() {

// 时间结束后进行相应逻辑处理

}

}.start();

countDownMap.put(holder.clock.hashCode(), holder.countDownTimer);

} else {

// 时间结束 进行相应逻辑处理

}

}

@Override

public int getItemCount() {

return 25;

}

class ClockViewHolder extends RecyclerView.ViewHolder {

TextView clock;

CountDownTimer countDownTimer;

public ClockViewHolder(View itemView) {

super(itemView);

clock = (TextView) itemView.findViewById(R.id.clock);

}

}

}

其中cancelAllTimer()这个方法解决了内存的问题,通过这行代码,将item的hashcode作为key设入SparseArray中,这样在cancelAllTimer方法中可以一个一个取出来进行倒计时取消操作。

countDownMap.put(holder.clock.hashCode(),holder.countDownTimer);

接着通过下面这行代码新建一个CountDownTimer类

holder.countDownTimer = new CountDownTimer(betweenDate, 1000) {

public void onTick(long millisUntilFinished) {

millisUntilFinished = millisUntilFinished / 1000;

int hours = (int) (millisUntilFinished / (60 * 60));

int leftSeconds = (int) (millisUntilFinished % (60 * 60));

int minutes = leftSeconds / 60;

int seconds = leftSeconds % 60;

final StringBuffer sBuffer = new StringBuffer();

sBuffer.append(addZeroPrefix(hours));

sBuffer.append(":") sBuffer.append(addZeroPrefix(minutes));

sBuffer.append(":");

sBuffer.append(addZeroPrefix(seconds));

holder.clock.setText(sBuffer.toString());

}

public void onFinish() {

// 时间结束后进行相应逻辑处理

}

}.start();

分析它的源码

public CountDownTimer(long millisInFuture, long countDownInterval) {

mMillisInFuture = millisInFuture;

mCountdownInterval = countDownInterval;

}

从中可以很清楚的看出,设置了两个值,第一个是倒计时结束时间,第二个是刷新时间的间隔时间。

然后通过start方法进行启动,接着看下start方法中进行的处理

public synchronized final CountDownTimer start() {

mCancelled = false;

if (mMillisInFuture <= 0) {

onFinish();

return this;

}

mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;

mHandler.sendMessage(mHandler.obtainMessage(MSG));

return this;

}

源码中,当倒计时截止时间小于等0时也就是倒计时结束时,调用了onFinish方法,若时间还未结束,则通过handler的异步消息机制,将消息进行发出,通过一整个流程,最终方法会走到handler的handleMessage方法中,如果有不熟悉这个异步流程的伙伴,可以去看我以前写的一篇异步消息机制的文章 android异步消息机制,源码层面彻底解析。好了,接下来就来看看handler的handleMessage方法。

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

synchronized (CountDownTimer.this) {

if (mCancelled) {

return;

}

final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

if (millisLeft <= 0) {

onFinish();

} else if (millisLeft < mCountdownInterval) {

// no tick, just delay until done

sendMessageDelayed(obtainMessage(MSG), millisLeft);

} else {

long lastTickStart=SystemClock.elapsedRealtime();

onTick(millisLeft);

// take into account user's onTick taking time to execute

long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

// special case: user's onTick took more than interval to

// complete, skip to next interval

while (delay < 0) delay += mCountdownInterval;

sendMessageDelayed(obtainMessage(MSG), delay);

}

}

}

};

相信这段源码还是很通熟易懂,首先计算出剩余时间,如果剩余时间小于刷新时间,就发送一条延时消息直到时间结束,如果剩余时间大于刷新时间就调用onTick(millisLeft)方法,这个方法在我们创建CountDownTimer类时就进行过重写,在里面就可以写我们倒计时展示的具体逻辑了。至此整个流程结束。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android列表倒计时,RecyclerView实现列表倒计时相关推荐

  1. android开发 RecyclerView 瀑布列表布局

    android开发 RecyclerView 瀑布列表布局 1.写一个内容的自定义小布局: <?xml version="1.0" encoding="utf-8& ...

  2. android开发实现选择列表,Android使用RecyclerView实现列表数据选择操作

    Android使用RecyclerView实现列表数据选择操作 发布时间:2020-08-31 17:50:13 来源:脚本之家 阅读:76 作者:迟做总比不做强 这些时间做安卓盒子项目,因为安卓电视 ...

  3. android之网络请求 -- 获取RecyclerView的列表项(图片 + 文字)

    android之网络请求 -- 获取RecyclerView的列表项 示意图,网络请求的地址,插件及依赖 代码架构 代码内容 MainActivity.java activity_main.xml R ...

  4. Android实战开发-Kotlin教程(入门篇-RecyclerView数据列表的实现)

    在移动应用开发中,很多时候我们需要去展示数据记录,如电商应用中的商品列表.订单列表等等一系列的数据记录的展示时,我们需要用到Android的列表组件展示这些数据,列表组件应该是我们遇到到比较常见也是必 ...

  5. 带倒计时RecyclerView的设计心路历程

    /   今日科技快讯   / 伴随着联想集团终止科创板IPO,在高负债率下已退休的柳传志约1亿元的高薪酬也被外界所质疑.此前有消息称,柳传志在香港上市公司联想集团拿317万美元的年薪,其在2020年的 ...

  6. 微信读书android换到ios,Android 微信读书本周推荐传送带列表实现

    实现效果 image 使用 android:id="@+id/carousel" android:layout_width="match_parent" and ...

  7. Android商城开发----点击左侧分类列表右侧更新对应列表内容

    Android商城开发----点击左侧分类列表右侧更新对应列表内容 目录 Android商城开发----点击左侧分类列表右侧更新对应列表内容 一.首先说布局: 二.主要说一下,布局完成后实现点击左侧类 ...

  8. Android 顶部标签栏及内容列表的设计与实现

    文章目录 一.使用ViewPager控件实现翻页效果 案例演示 1.主页面添加ViewPager控件 2.创建适配器继承FragmentPagerAdapter 3.为ViewPager对象设置适配器 ...

  9. Android学习系列(10)--App列表之拖拽ListView(上)

    研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨.       鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. ...

最新文章

  1. oracle审计功能ip地址,oracle 11g 审计功能
  2. [shiro学习笔记]第二节 shiro与web融合实现一个简单的授权认证
  3. 『飞秋』在ASP.NET服务器端过程中使用WebBrowser的注意事项
  4. dos打开计算机管理,小何 发布 DOS 命令打开控制面板各项东东 你们懂得...
  5. 68 个人脸landmark 点分布图
  6. HTML之表格的基本知识
  7. 【转载】Linux等类Unix系统学习用书那点事儿!
  8. mqtt 推送的客户端测试方法
  9. 图像坐标球面投影_从球面到平面的投影
  10. 【快递100】 物流公司对应编码分享(截止到2021-09-19 最新数据)
  11. PyCharm2017破解步骤
  12. 在Python中用WordCloud生成聊天记录热点词汇词云图
  13. Android9.0 短信发送和彩信接受流程
  14. alios things开发板_AliOS Things图形界面开发指南
  15. 公司发给你一个gitLab账号怎么配置项目!
  16. 小程序--时间处理(显示几分钟前,,几小时前,,几天前...)
  17. 好用的免费代理池搭建
  18. 评价类问题解决方法及模型汇总
  19. 南开大学张昊计算机,张昊(东北大学工商管理学院副教授)_百度百科
  20. Ubuntu下利用安装包手动安装Apache和Php

热门文章

  1. 3D模型欣赏:白发小恶魔女 次世代角色设计 毛发细腻
  2. 《JavaScript交互式网页设计》复习考试
  3. 西门子300 PLC 功能块及背景数据块的说明
  4. github账户登录ArcGIS developer并申请API key
  5. php取网盘真实链接,利用蓝奏做个人小文件网盘和获取真实下载地址
  6. unix系统病毒概述(转)
  7. 原型软件--Balsamiq Mockups
  8. win7局域网计算机 慢,Win7系统局域网访问文件速度缓慢怎么办
  9. 基于SSD的CCTSDB交通标识数据集目标检测
  10. 计算机毕业设计django基于python学生考试成绩数据分析与可视化系统(源码+系统+mysql数据库+Lw文档)