Android学习笔记4-自定义CountDownTimer

想要写一个倒计时函数,思路也就是获取系统时间,与倒计时时间数计算来时间倒计。没想到Google官方有CountDownTimer API,代码比较短,小白也读的懂。

CountDownTimer简单思路:

  • 构造函数初始化倒计时总时间与间隔时间
  • 虚拟函数onTick()与onFinish()交互倒计时结果
  • 利用handler处理倒计时,根据系统时间获取倒计时还剩余的时间,判断反馈onTick(比如一秒tick一下)/继续后台倒计时/结束倒计时

但源码也因为太简单,就与官方文档的例子一样,只能指定倒计时总时间与时间间隔。
本身自己的倒计时要求也不多,就是想增加暂停与恢复倒计时功能。但重载该class不太可行,主要是还需要修改handler,干脆就直接粘贴复制该代码,添加了自己需要的几行代码。如此自定义后的countdownTimer代码如下:(注释中“!add”就是自己添加的代码)

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
/**
 * 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:
 *
 * 
 * new CountDownTimer(30000, 1000) {
 *
 *     public void onTick(long millisUntilFinished) {
 *         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
 *     }
 *
 *     public void onFinish() {
 *         mTextField.setText("done!");
 *     }
 *  }.start();
 * 
* * 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. */ /** * customize from CountDownTimer * Created by zhubingning on 16/09/16. */ public abstract class CustomCountDownTimer { /** * Millis since epoch when alarm should stop. */ private final long mMillisInFuture; //!add,为了暂停时保存当前还剩下的毫秒数 private long mCurrentMillisLeft; /** * 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 CustomCountDownTimer(long millisInFuture, long countDownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countDownInterval; } //!add, 获取此时倒计时的总时间 public long getCountTimes(){ return mMillisInFuture; } /** * Cancel the countdown. */ //取消倒计时,handler从消息队列里取出message public synchronized final void cancel() { mCancelled = true; mHandler.removeMessages(MSG); } /** * Pause the countdown. */ //!add, 暂停,调用cancel()函数, mCurrentMillisLeft为全局变量自动保存 public synchronized final void pause() { cancel(); } /** * Resume the countdown. */ //!add, 恢复函数,根据mCurrentMillisLeft的值重新添加message开始倒计时 public synchronized final void resume() { mCancelled=false; if (mCurrentMillisLeft <= 0) { onFinish(); return ; } mStopTimeInFuture = SystemClock.elapsedRealtime() + mCurrentMillisLeft; mHandler.sendMessage(mHandler.obtainMessage(MSG)); return ; } /** * Start the countdown. */ //开始倒计时,handler发送消息到队列 public synchronized final CustomCountDownTimer 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 //handler private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { //同步线程 synchronized (CustomCountDownTimer.this) { //判断倒计时是否已取消 if (mCancelled) { return; } //计算当前剩余毫秒数 final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); //根据剩余毫秒数,或者结束倒计时,或者只延时,或者调用onTick并延时 if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { // no tick, just delay until done onTick(0);//!add sendMessageDelayed(obtainMessage(MSG), millisLeft); } else { long lastTickStart = SystemClock.elapsedRealtime(); mCurrentMillisLeft=millisLeft;//!add 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); } } } }; }

p.s. 附注知识:关于handler
“异步处理大师-handler“可以关联任意线程并添加消息(即task)到消息队列中,当相关线程的looper循环到自己的消息时,能够自动执行该消息(异步),执行完毕后再回到looper。
特别是上面的例子中handler中有delay处理,所以单独用handler处理比较合适。

Android学习笔记4-自定义CountDownTimer_第1张图片
1.handler发送消息到消息队列中

Android学习笔记4-自定义CountDownTimer_第2张图片
2.handler异步处理消息

* handler&多线程的参考文献:
android的消息处理机制(图+源码分析)——Looper,Handler,Message
Android之Handler用法总结

你可能感兴趣的:(Android学习笔记4-自定义CountDownTimer)