網(wǎng)上看了一堆各種Handler解析、詳解的,但是感覺流程沒有說透。我結合自己的理解和源碼來綜合性說說吧!
Handler源碼定義的兩大作用:
1.線程間通信
2.定時任務
一、Handler的初始化
我從定義構造方法開始講起吧!
Handler的構造方法主要有兩種,然后通過這兩種形成各種使用靈活的構造方法!
第一種:
public Handler(Callback callback, boolean async) {//hide方法,默認無法構造
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
相關的構造方法有:
public Handler() {
this(null, false);
}
public Handler(Callback callback) {
this(callback, false);
}
public Handler(boolean async) {//hide方法,默認無法構造
this(null, async);
}
第二種:
public Handler(Looper looper, Callback callback, boolean async) {//hide方法
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
對應的各種構造方法是:
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
兩種方法的核心區(qū)別就是Looper的初始化,但是兩種構造方法默認外部是無法調(diào)用的,Handler類隱藏了所有關于mAsynchronous的初始化設置!
先來說說第一種Handler的構建:
一來就是if判斷,還是一個私有靜態(tài)常量,一看就是用不上的,那么作用呢?
private static final boolean FIND_POTENTIAL_LEAKS = false;
官方解釋是:將此標志設置為true以檢測擴展的Handler類,如果不是靜態(tài)的匿名,本地或成員類, 這類可能會產(chǎn)生泄漏。
也就是我們常見構造時的警告說明!至于消除警告方法一般是設置成靜態(tài)或弱引用。繼續(xù)看下面的代碼
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
首先是默認Looper的構造初始化,關于這些變量,我們先看看聲明:
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
final boolean mAsynchronous;
全都用final修飾,也就是說每一個Handler只能綁定一個Looper、一個MessageQueue、一個Callback。至于我們用來發(fā)送和接收的Message則沒有任何限制!至于mAsynchronous一般構造方法獲取到的,都是默認的false,主要是針對Message的排隊處理!這里還有一點就是除了Callback外,其他變量都不能為空,否則消息處理時會拋異常,因為Callback接口內(nèi)部方法未實現(xiàn)時會調(diào)用本地的handlerMessage方法,兩者不同在于Callback的回調(diào)方法有boolean類型的返回值!
第二種構建方法就簡單了,直接把需要初始化的局部變量賦值就行了,這里沒什么可說的。
二、消息發(fā)送
Handler的消息發(fā)送主要有兩種,一種是post,另一種是send。
先來看post處理方法。post主要是自己開啟一個Runnable線程處理事件,并能指定事件的處理時間(延時多少時間處理)。重載方法如下:
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtFrontOfQueue(Runnable r)//特殊方法
{
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
從上面可以看出,post方法最終調(diào)用的還是send方法將消息添加到消息隊列,而且還都是final方法,不可重寫,也提高了執(zhí)行效率?,F(xiàn)在來講解第一個方法,其他類似。post方法默認調(diào)用了sendMessageDelayed(getPostMessage(r), 0); 。先來看看線程處理方法getPostMessage(r):
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
私有的靜態(tài)方法,是為了將處理事件添加到Message消息線程中,并返回了Message。
在看sendMessageDelayed方法
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
直接就是調(diào)用send方法了。也就是說post方法最后還是要調(diào)用send方法來將消息添加到消息隊列中,下面我們來看直接來看send方法。
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {//
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
public final boolean sendMessageAtFrontOfQueue(Message msg) {//特殊方法
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
還是從最簡單的sendMessage方法說起,直接調(diào)用sendMessageDelayed方法,繼續(xù)看,延時做了合法性判斷后調(diào)用了sendMessageAtTime方法,也就是指定任務的執(zhí)行發(fā)生時間。繼續(xù)看里面的代碼,先是獲取的此Handler的消息隊列MessageQueue,并做了null判斷,這里先不探討出現(xiàn)null的情況,繼續(xù)往下看,然后調(diào)用了enqueueMessage方法:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
這個私有方法就將消息添加到了消息隊列中,消息發(fā)送也就完成了。
在post和send方法中,有一種比較特殊的消息發(fā)送機制,就是消息插隊(備注的特殊方法),也就是postAtFrontOfQueue和sendMessageAtFrontOfQueue方法,因為postAtFrontOfQueue是通過sendMessageAtFrontOfQueue方法實現(xiàn)的,但最終還是一樣的,只不過這種方法會出排序問題或其他情況等,一般很少使用!
從上面可以看出,無論是post還是send方方法,都是將Message添加到MessageQueue中,Handler還提供了獲取Message的幾種構造方法:
public final Message obtainMessage()
{
return Message.obtain(this);
}
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
}
public final Message obtainMessage(int what, Object obj)
{
return Message.obtain(this, what, obj);
}
public final Message obtainMessage(int what, int arg1, int arg2)
{
return Message.obtain(this, what, arg1, arg2);
}
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
{
return Message.obtain(this, what, arg1, arg2, obj);
}
基本都是Message的構造方法,但全部沒有用new方法,而是通過obtain方法獲取,而這也是Message類推薦的。
到這里Handler的消息發(fā)送和發(fā)送相關的方法就基本講完了!Handler的主要方法之一也就講的差不多了!下一節(jié)繼續(xù)Handler的消息移除和消息處理!