Android 線程 Looper.prepare()、Looper.loop() 使用


優化項目過程中發現了一個非常Low的問題,整理一下。備忘:
說問題之前先看下HandlerThread的定義
一個封裝了looper的線程:  

Looper用於封裝了android線程中的消息循環。默認情況下一個線程是不存在消息循環(message loop)的,須要調用Looper.prepare()來給線程創建一個消息循環,調用Looper.loop()來使消息循環起作用。從消息隊列里取消息。處理消息。
注:寫在Looper.loop()之后的代碼不會被馬上執行。當調用后mHandler.getLooper().quit()后。loop才會中止,其后的代碼才干得以執行。

Looper對象通過MessageQueue來存放消息和事件。一個線程僅僅能有一個Looper。相應一個MessageQueue。


下面是Android API中的一個典型的Looper thread實現:

//Handler不帶參數的默認構造函數:new Handler()。實際上是通過Looper.myLooper()來獲取當前線程中的消息循環,
//而默認情況下。線程是沒有消息循環的,所以要調用 Looper.prepare()來給線程創建消息循環,然后再通過。Looper.loop()來使消息循環起作用。
[java]  view plain copy
  1. class LooperThread extends Thread  
  2. {  
  3. public Handler mHandler;  
  4. public void run()   
  5. {  
  6. Looper.prepare();  
  7. mHandler = new Handler()   
  8. {  
  9. public void handleMessage(Message msg)   
  10. {  
  11. // process incoming messages here  
  12. }  
  13. };  
  14. Looper.loop();  
  15. }  

另,Activity的MainUI線程默認是有消息隊列的。

所以在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,簡單,卻是問題~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM