官方提供的用法如下:

new CountDownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
} public void onFinish() {
mTextField.setText("done!");
}
}.start();

创建CountDownTimer实例之后,必须通过start()函数将计时器开启,才能保证CountDownTimer运行。CountDownTimer还提供了cancel()方法,可以将计时器取消。

在使用CountDownTimer时,必须实现两个方法:onTick() 和 onFinish()。 
在onTick(long millisUntilFinished) 中的参数millisUntilFinished是倒计时的剩余时间。在倒计时结束后会调用onFinish,倒计时结束后需要执行的操作可以写在onFinish中。

CountDownTimer(30000, 1000)中的30000,表示倒计时时间为30秒,1000表示每隔1秒钟调用一次onTick方法。

方法详解:

onTick的调用是同步的,保证这次调用不会在之前调用完成前发生。这里的同步机制主要是用来:onTick的实现需要很多时间执行比倒计时间隔更重要的事情。 
构造函数 
         public CountDownTimer (long millisInFuture, long countDownInterval) 
参数 
        millisInFuture  从开始调用start()到倒计时完成并onFinish()方法被调用的毫秒数。(倒计时时间,单位毫秒) 
        countDownInterval  接收onTick(long)回调的间隔时间。(单位毫秒) 
公共方法 
  public final void cancel () 
       取消倒计时(将会停止倒计时,5.0之前的系统不能在onTick()中调用)        
                  
  public abstract void onFinish () 
       倒计时完成时被调用

  public abstract void onTick (long millisUntilFinished) 
       固定间隔被调用 
参数 
       millisUntilFinished   倒计时剩余时间。 
  public synchronized final CountDownTimer start () 
       启动倒计时

在使用过程中发现,在一个activity或者fragment中开启了计时器,如果倒计时没有完成即退出activity或者fragment,此时onTick仍然会继续执行,当执行到mTextField.setText()时,mTextField为null,导致程序crash。因此需要在onTick中进行非空判断。

如果是在Fragment中:

if(getActivity()!=null){
//todo
}

如果是在Activity中:

if(!activity.isFinishing()){
//todo
}

但是我们不希望在fragment或activity退出之后仍然调用onTick,即使已经做了非空判断。 
我们希望在退出之后CountDownTimer也随之停止,因此在onTick中,当getActivity()==null或者activity.isFinishing()==true的时候,可以使用cancel方法取消掉计时器。

But!!! 
经过实验发现,cancel在onTick中调用,是无法成功取消计时器的。 
调用cancel之后,仍然会每隔固定时间调用onTick方法。 
然而,在5.0及以上的系统中,cancel方法就可以起到作用。对比CountDownTimer的源码发现,在5.0中,增加了一个字段

 /**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false;

通过mCancelled 标识当前计时器是否取消。 
然后在handleMessage()中首先对mCancelled进行判断:

// handles counting down
private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) { synchronized (CountDownTimer.this) {
if (mCancelled) { //**Attention!!!**
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中调用cancel方法取消计时器,可以自定义一个CountDownTimerUtil,将5.0以上的CountDownTimer源码复制到CountDownTimerUtil即可。

附5.0以上系统的代码:

/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package android.os; /**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* Example of showing a 30 second countdown in a text field:
*
* <pre class="prettyprint">
* new CountDownTimer(30000, 1000) {
*
* public void onTick(long millisUntilFinished) {
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
* }
*
* public void onFinish() {
* mTextField.setText("done!");
* }
* }.start();
* </pre>
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimer { /**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture; /**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval; private long mStopTimeInFuture; /**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false; /**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
} /**
* Cancel the countdown.
*/
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
} /**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
} /**
* Callback fired on regular interval.
* @param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished); /**
* Callback fired when the time is up.
*/
public abstract void onFinish(); private static final int MSG = 1; // 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(); 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);
}
}
}
};
}

4.4系统的代码

/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package android.os; import android.util.Log; /**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* Example of showing a 30 second countdown in a text field:
*
* <pre class="prettyprint">
* new CountDownTimer(30000, 1000) {
*
* public void onTick(long millisUntilFinished) {
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
* }
*
* public void onFinish() {
* mTextField.setText("done!");
* }
* }.start();
* </pre>
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimer { /**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture; /**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval; private long mStopTimeInFuture; /**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
} /**
* Cancel the countdown.
*/
public final void cancel() {
mHandler.removeMessages(MSG);
} /**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
} /**
* Callback fired on regular interval.
* @param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished); /**
* Callback fired when the time is up.
*/
public abstract void onFinish(); private static final int MSG = 1; // handles counting down
private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) { synchronized (CountDownTimer.this) {
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);
}
}
}
};
}

Android CountDownTimer的使用的更多相关文章

  1. Android CountDownTimer倒计时器的使用

    http://blog.csdn.net/freesonhp/article/details/25904047 在平时我们编程的时候,经常会用到倒计时这个功能,很多人不知道Android已经帮封装好了 ...

  2. Android CountDownTimer 类实现倒计时

    本文用 Android 中的 CountDownTimer 类实现倒计时功能,类似输入手机号获得验证码.界面如下所示: 1. 点击 “开始计时” 按钮后开始进行倒计时, 2. 倒计时过程: 3. 时间 ...

  3. Android CountDownTimer 倒计时

    摘自:http://www.cnblogs.com/over140/archive/2011/12/20/2294220.html 继承关系 public abstract class CountDo ...

  4. android CountDownTimer

    最近进行的项目使用的定时功能,我发现了一个非常容易使用内置类CountDownTimer.当然,可以使用这种效果TimerTask + Timer为了实现.只是我个人的意见CountDownTimer ...

  5. Android使用CountDownTimer倒计时

    1.布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android ...

  6. 拓展 Android 原生 CountDownTimer 倒计时

    拓展 Android 原生 CountDownTimer 倒计时 [TOC] CountDownTimer 在系统的CountDownTimer上进行的修改,主要是拓展了功能,当然也保留了系统默认的模 ...

  7. [Android Pro] CountDownTimer倒计时

    定时执行在一段时候后停止的倒计时,在倒计时执行过程中会在固定间隔时间得到通知(译者:触发onTick方法),下面的例子显示在一个文本框中显示一个30s倒计时: new CountdownTimer(3 ...

  8. Android基础之CountDownTimer 倒计时类

    app常用的60s倒计时计时功能: private static final int TIME_LIMIT = 60; private void initView() { // 相关控件 mResen ...

  9. Android中使用Handler以及CountDownTimer实现包含倒计时的闪屏页面

    上一篇博文<Android中Handler使用浅析>通过实现倒计时闪屏页面的制作引出了Handler的使用方法以及实现原理,博文末尾也提到了实现过程中的Bug,有兴趣的朋友可以点击链接回去 ...

随机推荐

  1. Spring框架系列(一)--Spring MVC基础知识

    Web项目开发过程中一般都是使用MVC(Model-View-Controller)模式,早先的Struts2到Spring MVC,再到现在Spring Boot,都是相似的思 路.Spring B ...

  2. 浅谈FFC

    FFC(Flexible Formatting Context) CSS3引入了一种新的布局模型——flex布局(之前有文章介绍过).flex是flexible box的缩写,一般称之为弹性盒模型.和 ...

  3. 05Microsoft SQL Server 表创建,查看,修改及删除

    Microsoft SQL Server 表创建,查看,修改及删除 创建表 创建普通表 use 数据库名称 go create table 表名称( 列1 ) not null, 列2 ) not n ...

  4. Codeforces985E. Pencils and Boxes (单调队列)

    题意:n个数 把他们放进一些盒子里 每个盒子最少放k个数 且最小和最大的差不能大于d 题解:显然排个序 对于当前点 存一下前面有哪些节点可以当作结尾 那么就可以枚举这些点的下一个点作为起点能否和当前点 ...

  5. 2019西安多校联训 Day4

    T1 大水题!!难度简单,显然的贪心策略即可,but... 思路:首先我们按与i点作战后活下来的士兵排序,然后 若当前剩余兵力足够直接减掉战斗死亡人数,如果不够就加 够再打它,但是!我们在考完试观察测 ...

  6. 洛谷——P1404 平均数

    P1404 平均数 题目描述 给一个长度为n的数列,我们需要找出该数列的一个子串,使得子串平均数最大化,并且子串长度>=m. 前缀和+二分答案 #include<iostream> ...

  7. ROW_NUM

    SELECT  *  FROM ( (SELECT ROW_NUMBER() OVER (PARTITION BY  字段1,字段2  ORDER BY 字段3   DESC) AS  TMPID), ...

  8. Python学习第二阶段Day2(json/pickle)、 shelve、xml、PyYAML、configparser、hashlib模块

    1.json/pickle   略. 2.shelve模块 import shelve # shelve 以key value的形式序列化,value为对象 class Foo(object): de ...

  9. vs2012+ winform+.net4.0发布如何在xp上运行

    今天在英文版vs2013打包发布4.0(非4.0 client)的winform时,遇到了在xp上无法运行的情况,.net framework 4.0在xp上已安装.在打包前,winform工程,即菜 ...

  10. Django-F和Q函数作用与使用

    F函数 能够解析对现有查询对象的引用的对象. obj = Score.objects.get(stuid=') obj.score += 1 obj.order.save() 执行出的SQL语句 wh ...