Handler機制的問題
Handler機制的問題
相信很多人都遇到過這樣的面試題。
那為什麼需要Handler呢,你們有反問過自己 || 面試官嗎?
看完這篇文章相信你下次去面試就能好好的刷一下面試官的氣焰了(裝逼),畢竟很多公司本身沒有Android開發人員,面試題都是網上找的,或者理解不深。
為什麼要有Handler
從原始碼角度理解該機制
本文為樓主原創,轉載請表明出處:http://blog.csdn.net/Suma_sun/article/details/51427312
Handler的由來
首先為什麼需要Handler呢? ——因為UI更新只能在UI執行緒。
那為什麼只能在UI執行緒更新UI呢?——因為Android是單執行緒模型。
那為什麼Android是單執行緒模型?
那是因為如果任意執行緒都可以更新UI的話,執行緒安全問題處理起來會相當麻煩複雜,所以就規定了Android是單執行緒模型,只允許在UI執行緒更新UI操作。
Handler機制
Handler機制有幾個核心類:Handler、Looper、Message、MessageQueue。
Handler機制是一個典型的生產者消費者模式——多個生產者,一個消費者,該模式是處理執行緒安全的一個經典模式,如果不瞭解的請自行查閱相關資料,不懂也沒關係,並不影響接下來的內容。
關聯Looper
首先我們常用的構造方法
/**
* Default constructor associates this handler with the {@link Looper} for the current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*/
public Handler() {
this(null, false);
}
預設的構造器 new Handler() 會從當前執行緒獲取Looper關聯。
如何關聯呢?
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
下面這個構造是所有傳入null Looper的歸屬
//預設不開啟
private static final boolean FIND_POTENTIAL_LEAKS = false;
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
//當子類是匿名類 或者 是成員類 或者 本地類時
//並且不是靜態類時進行列印
//獲取該類的修飾符 & 靜態修飾符常量,&位運算,將值轉為二進位制進行對位比較,當某一位都為1時該位結果為1,只要某位有一個為0時結果位為0
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;
}
mLooper = Looper.myLooper();//關聯Looper關鍵程式碼
//Return the Looper object associated with the current thread. Returns null if the calling thread is not associated with a Looper.
意思是返回當前執行緒的Looper物件,如果為空告知執行緒關聯Looper
所以當我們在Activity中建立Handler沒問題,而在子執行緒中建立會報錯的原因就在這裡
獲取訊息
在Looper中有一函式loop();該函式會一直輪循獲取訊息,直到沒有訊息返回退出。
//......
for (;;) {
//......
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
......
}
在MessageQueue中找到next()方法
Message next() {
//......
for(;;){
//......
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
return msg;
}
}
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
//......
}
該方法也是一個輪循,並且是帶同步塊的操作,直到返回Message,或者呼叫quit(boolean safe)方法 改變mQuitting 使其返回null。
//Looper
public void quit() {
mQueue.quit(false);
}
處理訊息
獲取到Message後會呼叫其持有的Handler物件dispatchMessage(msg)方法
msg.target.dispatchMessage(msg);
Message中找到如下程式碼
Handler target;
Runnable callback;
Handler
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
Handler收到訊息後,先判斷訊息內的回撥Runnable是否為空//post(Runnable)等方法
,為空就呼叫Handler內部的Runnable,
public Handler(Callback callback) {
this(callback, false);
}
public Handler(Looper looper) {
this(looper, null, false);
}
然後呼叫handleMessage(msg);
public interface Callback {
public boolean handleMessage(Message msg);
}
上面已經就這原始碼關鍵程式碼梳理了一遍,部分程式碼並不全面,請各位自行檢視原始碼,這樣更加深刻。
相關文章
- handler機制的原理
- Handler機制解析
- Handler機制原理
- Handler 機制分析
- 再讀Handler機制
- Handler訊息機制完全解析Handler解析
- 學習 Android Handler 訊息機制需要注意這些問題!Android
- Handler訊息機制及handler原理(Handler,Looper,MessageQueue),自定義HandlerOOP
- Android Handler機制之Handler 、MessageQueue 、LooperAndroidOOP
- Handler 機制再瞭解
- Android Handler機制理解Android
- update的機制問題
- Android的Handler訊息機制 解析Android
- android訊息機制—HandlerAndroid
- Android訊息機制HandlerAndroid
- Handler訊息傳遞機制
- Android Handler機制詳解Android
- 終於明白了Handler的執行機制
- Android 的 Handler 機制實現原理分析Android
- Android Handler機制之ThreadLocalAndroidthread
- Android訊息機制Handler用法Android
- Android Handler機制之Message及Message回收機制Android
- Android 原始碼分析(二)handler 機制Android原始碼
- Android Handler 訊息機制詳述Android
- Android Handler機制之總目錄Android
- Android Handler機制使用,原始碼分析Android原始碼
- 面試:Handler 的工作機制是怎樣的呢?面試
- 原始碼深度解析 Handler 機制及應用原始碼
- 一文讀懂 Handler 機制全家桶
- 【Android原始碼】Handler 機制原始碼分析Android原始碼
- 深入探索Android訊息機制之HandlerAndroid
- GC機制和OutOfMemory問題的診斷GC
- Android Handler機制之Message的傳送與取出Android
- Android中handler問題彙總Android
- Handler 訊息機制以及記憶體洩漏記憶體
- Android 之 “只是想來談談 Handler 機制”Android
- Android 訊息機制:Handler、MessageQueue 和 LooperAndroidOOP
- Android Handler機制理解和AsyncTask使用小記Android