官方提供的用法如下:

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. 05C语言数组

    C语言数组 一维数组 类型符 数组名[常量表达式] #include <stdio.h> int main(){ ] = {,,,}; int a; ;a<;a++){ printf ...

  2. maven deploy时报错

    Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on p ...

  3. xmpp 消息和好友上下线(3)

    原始地址:XMPPFrameWork IOS 开发(四) 消息 //收到消息 - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XM ...

  4. <SpringMvc>入门三 参数绑定

    1.get请求 <%--请求参数的绑定--%> <%--get请求参数--%> <a href="/param/testParam1?username=tom& ...

  5. 爬虫实战(二) 用Python爬取网易云歌单

    最近,博主喜欢上了听歌,但是又苦于找不到好音乐,于是就打算到网易云的歌单中逛逛 本着 "用技术改变生活" 的想法,于是便想着写一个爬虫爬取网易云的歌单,并按播放量自动进行排序 这篇 ...

  6. python3 判断大小写

    转自http://wangwei007.blog.51cto.com/68019/1134323 # 一.pyhton字符串的大小写转换, 常用的有以下几种方法: # 1.对字符串中所有字符(仅对字母 ...

  7. Datatable 导出到execl 官网demo

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content ...

  8. DESEncrypt对称加密解密

    分享一个很好用的DESEncrypt对称加密解密的类 using System; using System.Security.Cryptography; using System.Text; usin ...

  9. 在Eclipse中设置Maven插件

    [步骤] Maven插件的设置: ①installations:指定Maven核心程序的位置.不建议使用Maven插件自带的Maven程序,而应该使用我们自己解压的那个. ②user settings ...

  10. Java基础学习总结(75)——Java反射机制及应用场景

    什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...