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

 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. 关于Python2和Python3之间的文本模型改变

    原文地址:http://python-notes.curiousefficiency.org/en/latest/python3/questions_and_answers.html#what-act ...

  2. Java DB 访问(三)mybatis mapper interface接口

    1 项目说明 项目采用 maven 组织 ,依赖 mysql-connector-java,org.mybatis,junit pom 依赖如下: mysql 数据连接 : mysql-connect ...

  3. 跨站脚本攻击(xss)理解

    一  概念 攻击者不直接攻击受害者,而是利用受害者登陆的网站中的漏洞,对受害者进行攻击. 二  危害 由于js本身的限制,并不能直接对用户的电脑造成侵害,但是可以: 1. 获取用户的storage,c ...

  4. opencv实现canopy算法

    #include "stdafx.h" using namespace cv; int main(int argc, char** argv) { Mat img=imread(& ...

  5. IdentityServer4 Hybrid 模式

    原文参考:Switching to Hybrid Flow and adding API Access back 接上篇:IdentityServer-Protecting an API using ...

  6. 安装flutter和dart总结

    1 manjaro从软件仓库安装就行,但是也可以下载安装包.然后添加到Path目录 我是安装dart从软件仓库, flutter下载压缩包添加到path 1.1 需要将android sdk , ex ...

  7. Java集合——HashMap,HashTable,ConcurrentHashMap区别

    Map:“键值”对映射的抽象接口.该映射不包括重复的键,一个键对应一个值. SortedMap:有序的键值对接口,继承Map接口. NavigableMap:继承SortedMap,具有了针对给定搜索 ...

  8. Dubbo剖析-SPI机制

    文章要点: 1.什么是SPi 2.Dubbo为什么要实现自己的SPi 3.Dubbo的IOC和AOP 4.Dubbo的Adaptive机制 5.Dubbo动态编译机制 6.Dubbo与Spring的融 ...

  9. 【详解】核心组件之UserDetailService

    简介 UserDetails => Spring Security基础接口,包含某个用户的账号,密码,权限,状态(是否锁定)等信息.只有getter方法. Authentication => ...

  10. Golang 接口interface

    接口interface 接口是一个或多个方法签名的集合 只要某个类型拥有该接口的所有方法签名,即算实现该接口,无需显示声明实现了哪个接口,这成为Structural Typing 接口只有方法声明,没 ...