倒计时的功能,比如说:发送短信验证码倒计时。

 public class CountDownTimerActivity extends Activity {

     private Button mSend;
private SendCountMessage mCountMessage; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_countdown); mCountMessage = new SendCountMessage();
mSend = (Button) findViewById(R.id.sendCode);
mSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSend.setClickable(false);
//开始执行倒计时的功能
mCountMessage.start();
}
});
} /**
* 我们继承这个抽象类,然后设置好总共的倒计时的时间,以及间隔的时间
* 并且重写 onTick和onFinish方法
*/
class SendCountMessage extends CountDownTimer { /**
* 这里我们还需要设置两个参数:
* 第一个参数:表示我们倒计时的总时间
* 第二个参数:表示我们倒计时的间隔,比如说我们是按一秒数还是二秒
*/
public SendCountMessage() {
super(, );
} /**
* 该方法表示会在构造方法中设定的间隔时间下调用这个方法的。
* 比如说我们设置了间隔时间为1秒的话,那么CountDownTimer
* 将会每个一秒的时间调用 onTick方法一下
* @param millisUntilFinished 表示距离倒计时结束的时间
*/
public void onTick(long millisUntilFinished) {
mSend.setText(millisUntilFinished/ + " 秒后重发");
} /**
* 这里表示倒计时完成结束了
*/
public void onFinish() {
mSend.setClickable(true);
}
} @Override
protected void onDestroy() {
super.onDestroy();
/**
* 最后在这里的时候,我们需要将CountDownTimer取消掉,因为如果我们在销毁界面的时候
* 还没有取消该倒计时器的话,它还会一直在后台不断的跑的直到结束倒计最后才会结束的,
* 这样子为了以免出现问题,我们这里需要取消掉,并且让系统gc该变量。
*/
if(mCountMessage != null) {
mCountMessage.cancel();
mCountMessage = null;
}
}
}

界面布局:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> ........ <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginTop="20dip"> <EditText
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight=""
android:inputType="number"
android:hint="请输入验证码" /> <Button
android:id="@+id/sendCode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送验证码"
android:textSize="18sp" /> </LinearLayout> </LinearLayout>

当我们不需要使用倒计时功能的时候,一定要要调用cancel()方法取消掉,不然它还会在我们页面销毁的时候继续执行的,很有可能会导致内存泄漏的问题

代码分析

 public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
} public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= ) {
onFinish();
return this;
}
//通过当前开始的时间 + 倒计时的总时间来计算出结束的毫秒值
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
//然后发送一个message消息给mHandler
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}

mHandler里面的代码:

 // handles counting down
private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) { synchronized (CountDownTimer.this) {
//如果用户主动调用了取消方法,则返回
if (mCancelled) {
return;
} //第一步:首先判断结束的时间跟当前时间的差。
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); //条件一: 如果小于等于0了,说明结束了。
if (millisLeft <= ) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
//条件二: 如果距离结束的时间小于我们设定的间隔时间值的时候
// 这个时候就发送一个millisLeft延时的消息
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 < ) delay += mCountdownInterval; //发送一个延时的,时间间隔为我们设定的mCountdownInterval的消息出去
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};

在创建构造函数之前会创建一个内部的Handler对象,主要是用于定时发送消息用的。当我们调用start()方法的时候会发送一个Handler消息出来,这个时候会在mHandler中进行处理。

当Handler收到消息之后就会去跟设定的时间间隔值进行一个比对,然后就发送一个延时的消息。

public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}

CountDownTimer 源码分析的更多相关文章

  1. Android 关于 CountDownTimer onTick() 倒计时不准确问题源码分析

    一.问题 CountDownTimer 使用比较简单,设置 5 秒的倒计时,间隔为 1 秒. final String TAG = "CountDownTimer"; * , ) ...

  2. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  3. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  4. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  5. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  6. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  7. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  8. java使用websocket,并且获取HttpSession,源码分析

    转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...

  9. ABP源码分析二:ABP中配置的注册和初始化

    一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...

随机推荐

  1. 自定义 Scrapy 爬虫请求的 URL

    之前使用 scrapy 抓取数据的时候 ,默认是在逻辑中判断是否执行下一次请求 def parse(self): # 获取所有的url,例如获取到urls中 for url in urls: yiel ...

  2. ASP.NET Core 1.0 Configuration 配置管理

    documentation: https://docs.asp.net/en/latest/fundamentals/configuration.html github: https://github ...

  3. Spring Cloud Eureka

    搭建服务注册中心 创建eureka-center,pom.xml如下: <?xml version="1.0" encoding="UTF-8"?> ...

  4. Docker概念学习系列之Docker与传统虚拟机差异(4)

    不多说,直接上干货! 见[博主]撰写的https://mp.weixin.qq.com/s/YihjPONUcUi4b_7RC8oLYw   传统虚拟化是在硬件层面实现虚拟化,需要有额外的虚拟机管理应 ...

  5. 轻量级web富文本框——wangEditor使用手册(5)——配置“插入代码”功能

    最新版wangEditor: demo.文档:http://www.wangEditor.github.io/ 下载地址:https://github.com/wangfupeng1988/wangE ...

  6. nginx反向代理如何获取真实IP?

    由于客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址. 1.安装--with-http_realip_ ...

  7. Async异步编程入门示例

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  8. Android so 文件进阶<二> 从dlsym()源码看android 动态链接过程

    0x00  前言 这篇文章其实是我之前学习elf文件关于符号表的学习笔记,网上也有很多关于符号表的文章,怎么说呢,感觉像是在翻译elf文件格式的文档一样,千篇一律,因此把自己的学习笔记分享出来.dls ...

  9. git命令小记

    1.git之tag git标签分为轻量级(lightweight)标签和含标注(annotated)标签.轻量级标签一般用于不会改变的分支,含标注的标签包含详细的信息. 轻量级标签: git tag ...

  10. C#Redis集合set

    快过年了,任务也没那么多了,可以有时间了解下其他的内容,今天看到一个博客关于weex的,觉得还挺实用的,等有空了可以了解了解.不过还是把今年的目标要完成.今天继续redis. 一.前戏 在Redis中 ...