Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android系統教程 >> Android開發教程 >> Android Handler、Message完全解析,帶你從源碼的角度徹底理解

Android Handler、Message完全解析,帶你從源碼的角度徹底理解

編輯:Android開發教程

之前也是由於周末通宵看TI3比賽,一直沒找到時間寫博客,導致已經有好久沒更新了。慚愧!後面還會 恢復進度,盡量保證每周都寫吧。這裡也是先恭喜一下來自瑞典的Alliance戰隊奪得了TI3的冠軍,希望明年 中國戰隊能夠虎起!

開始進入正題,我們都知道,Android UI是線程不安全的,如果在子線程中嘗試 進行UI操作,程序就有可能會崩潰。相信大家在日常的工作當中都會經常遇到這個問題,解決的方案應該也 是早已爛熟於心,即創建一個Message對象,然後借助Handler發送出去,之後在Handler的handleMessage() 方法中獲得剛才發送的Message對象,然後在這裡進行UI操作就不會再出現崩潰了。

這種處理方式被 稱為異步消息處理線程,雖然我相信大家都會用,可是你知道它背後的原理是什麼樣的嗎?今天我們就來一 起深入探究一下Handler和Message背後的秘密。

首先來看一下如何創建Handler對象。你可能 會覺得挺納悶的,創建Handler有什麼好看的呢,直接new一下不就行了?確實,不過即使只是簡單new一下, 還是有不少地方需要注意的,我們嘗試在程序中創建兩個Handler對象,一個在主線程中創建,一個在子線程 中創建,代碼如下所示:

public class MainActivity extends Activity {  
          
    private Handler handler1;  
          
    private Handler handler2;  
      
    @Override
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        handler1 = new Handler();  
        new Thread(new Runnable() {  
            @Override
            public void run() {  
                handler2 = new Handler();  
            }  
        }).start();  
    }  
      
}

如果現在運行一下程序,你會發現,在子線程中創建的Handler是會導致程序崩潰的,提示的錯誤 信息為 Can't create handler inside thread that has not called Looper.prepare() 。說是不能在 沒有調用Looper.prepare() 的線程中創建Handler,那我們嘗試在子線程中先調用一下Looper.prepare()呢 ,代碼如下所示:

new Thread(new Runnable() {  
    @Override
    public void run() {  
        Looper.prepare();  
        handler2 = new Handler();  
    }  
}).start();

果然這樣就不會崩潰了,不過只滿足於此顯然是不夠的,我們來看下Handler的源碼, 搞清楚為什麼不調用Looper.prepare()就不行呢。Handler的無參構造函數如下所示:

public 

Handler() {  
    if (FIND_POTENTIAL_LEAKS) {  
        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 = null;  
}

可以看到,在第10行調用了Looper.myLooper()方法獲取了一個Looper對象,如果Looper對象為空 ,則會拋出一個運行時異常,提示的錯誤正是 Can't create handler inside thread that has not called Looper.prepare()!那什麼時候Looper對象才可能為空呢?這就要看看Looper.myLooper()中的代碼 了,如下所示:

public static final Looper myLooper() {  
    return (Looper)sThreadLocal.get();  
}

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved