背景
有時候需要在子線程中進行耗時的 I/O 操作,讀取文件或者訪問網絡等,當耗時操作完成以後可能需要在 UI 上做一些改變,由於 Android 開發規範的限制,不能在子線程中訪問 UI 控件,否則就會觸發程序異常,這個時候通過 Handler 就可以將更新 UI 的操作切換到主線程中執行。
相關類
- Handler
- Looper(消息循環)
- Message(消息)
- MessageQueue(存儲消息)
Handler
package android.os;
public class Handler
public Handler(Callback callback, boolean async) {
...// 省略其他代碼
// 獲取當前線程的 Looper 對象,如果沒有則拋出異常
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
// 綁定消息隊列對象
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
創建 Handler
對象時,自動關聯當前線程的 Looper
對象,綁定相應的消息隊列對象。
Looper
package android.os;
public final class Looper
// Looper初始化
public static void prepare()
// 消息循環
public static void loop()
// ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
// 創建消息隊列對象,當創建Looper實例時,會自動創建與之關聯的消息隊列實例
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
FAQ
android 主線程中 Looper.loop() 爲什麼不會造成程序 ANR?