两种方法的区别
那么,为什么 Android 系统会提供两种方法来发送消息任务呢?这当然和使用场景相关了,根据不同的使用场景,这两种方法还是有区别的。当然,在平常的使用过程中或许你不会考虑这么多,因为在具体的使用场景中,你很可能“不经意”地就将两种方法的使用场景给区别开了:
-
当发送者知道如何处理消息的话,使用
Handler.post()
方法。发送者直接在 run() 方法中处理任务。 -
当接收者知道如何处理消息的话,使用
Handler.sendMessage()
方法。发送者将 Message 对象发射出去后,handler (接收者)调用 handleMessage() 方法处理任务。
实例:倒计时
下面,我们用 Handler 来实现倒计时功能。先来分析一下倒计时
的相关功能需求:
-
需要知道总时间和每一步的间隔时间。
-
每次到了间隔时间就回调通知,总时间结束后也要回调通知。
根据这个需求,我们可以大致猜想一下如何实现:
-
需要提供两个构造参数的构造方法,一个是总时间,一个是间隔时间。
-
需要提供两个抽象方法供子类实现,一个是每次到了间隔时间的回调通知,另一个是总时间结束后的回调通知。
有了这个思路,实现就很简单了,下面直接给出代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
public abstract class Timer { private long mMillisInFuture; private long mCountdownInterval; private long mStopTimeInFuture; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // 计算剩余时间 long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) { // 如果剩余时间小于或等于 0, 则回调 onFinish() 方法。 onFinish(); } else if (millisLeft < mCountdownInterval) { // 当剩余时间小于一次间隔时间时,不回调 onTick() 方法,直接等到最后再发送 sendMessageDelayed(obtainMessage(), millisLeft); } else { // 回调 onTick() 方法,并在一次间隔时间后再次发送消息。 onTick(millisLeft); sendMessageDelayed(obtainMessage(), mCountdownInterval); } } }; public Timer(long millisInFuture, long countdownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countdownInterval; } /** * 调用 start() 方法以启动倒计时 * @return */ public Timer start() { if (mMillisInFuture < 0) { onFinish(); return this; } // 获取倒计时完成的系统时间 mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; // 发送第一个消息 mHandler.sendMessage(mHandler.obtainMessage()); return this; } /** * 每经过一次间隔时间就回调一次 onTick 方法 * @param millionLeft 剩余时间 */ abstract void onTick(long millionLeft); /** * 倒计时完成后,回调 onFinish() 方法 */ abstract void onFinish(); } |
其实上面的代码是 Android 系统中 CountDownTimer
类的简化版,CountDownTimer
增加了线程安全机制并处理了一些特殊情况,有兴趣的朋友可以自行查阅。