優化項目過程當中發現了一個很是Low的問題,整理一下。備忘:java
說問題以前先看下HandlerThread的定義android
一個封裝了looper的線程: 異步
Looper用於封裝了android線程中的消息循環。默認狀況下一個線程是不存在消息循環(message loop)的,需要調用Looper.prepare()來給線程建立一個消息循環,調用Looper.loop()來使消息循環起做用。從消息隊列裏取消息。處理消息。ide
注:寫在Looper.loop()以後的代碼不會被立刻執行。當調用後mHandler.getLooper().quit()後。loop纔會停止,其後的代碼才幹得以執行。函數
Looper對象經過MessageQueue來存放消息和事件。一個線程僅僅能有一個Looper。相應一個MessageQueue。oop
下面是Android API中的一個典型的Looper thread實現:post
//Handler不帶參數的默認構造函數:new Handler()。其實是經過Looper.myLooper()來獲取當前線程中的消息循環,
//而默認狀況下。線程是沒有消息循環的,因此要調用 Looper.prepare()來給線程建立消息循環,而後再經過。Looper.loop()來使消息循環起做用。優化
[java] view plaincopyui
另,Activity的MainUI線程默認是有消息隊列的。this
因此在Activity中新建Handler時,不需要先調用Looper.prepare()。
那麼遇到了有多Low的問題呢:
項目中重寫了一個HandlerThread,而後定義了post方法。而後在主線程中例如如下實現:
AsyncHandler.post(new Runnable() {
@Override
public void run() {
try {
Looper.prepare();
// 一坨要異步運行的代碼******
Looper.loop();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
那麼明眼人一看就看出問題來了 ,這代碼一跑異步代碼確定運行不到啊。爲啥呢。且看下prepare的實現:
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
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));
}
So,簡單,倒是問題~