public static boolean isInMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
原理:主執行緒啟動時系統呼叫 Looper.prepareMainLooper(),將主 Looper 存入靜態 sMainLooper 並綁定到主執行緒的 ThreadLocal。其他執行緒預設無 Looper(myLooper() 回傳 null),或手動 Looper.prepare() 建立專屬 Looper,皆與主 Looper 物件不同。
| 場景 | myLooper() | getMainLooper() | 結果 |
|---|---|---|---|
| 主執行緒 | Looper{@40d35ef8} | Looper{@40d35ef8} | true |
| 普通子執行緒 | null | Looper{@40d35ef8} | false |
| HandlerThread / Looper.prepare() | Looper{@40d72c58} | Looper{@40d35ef8} | false |
// Looper.java 關鍵片段
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
private static Looper sMainLooper;
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) { sMainLooper = myLooper(); }
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) throw new RuntimeException("Only one Looper per thread");
sThreadLocal.set(new Looper(quitAllowed));
}
public static Looper myLooper() { return sThreadLocal.get(); }
public static Looper getMainLooper() { return sMainLooper; }
Thread.currentThread().getName().equals("main") 不可靠,名稱可被修改。new Handler(Looper.getMainLooper()) 只能驗證能否向主執行緒送訊息,非判斷當前執行緒身分。
if (isInMainThread()) {
updateUI();
} else {
new Handler(Looper.getMainLooper()).post(this::updateUI);
}
或搭配 runOnUiThread() (Activity)、View.post() 等封裝 API。