android的looper,handler訊息小結

來源:互聯網
上載者:User

  在Android開發中,為了UI線程能及時響應需要避免在其中執行耗時操作,以防止介面假死甚至ANR。我們一般把耗時操作如下載,查詢放在一個單獨的線程中。這之後再將結果更新到UI介面。android平台在非UI線程中更新介面大致有以下幾種方式:


[java]
<SPAN style="COLOR: #993300">Activity.runOnUiThread(Runnable)  
View.post(Runnable)  
AsyncTask<Params, Progress, Result>  
Handler.post(Runnable)</SPAN> 

Activity.runOnUiThread(Runnable)
View.post(Runnable)
AsyncTask<Params, Progress, Result>
Handler.post(Runnable)

 


其中後面兩種方式我們用的比較多,而AsyncTask也是基於Handler進行封裝的,可以看出Handler是我們更新UI線程的利器。看下常用的Handler構造方法:

[java] 
<SPAN style="COLOR: #993300">public Handler() { 
   this(null, false); 

public Handler(Callback callback, boolean async) { 
    ..... 
    mLooper = Looper.myLooper(); 
    ..... 
    mQueue = mLooper.mQueue; 
    mCallback = callback; 
    mAsynchronous = async; 
}</SPAN> 

public Handler() {
   this(null, false);
}
public Handler(Callback callback, boolean async) {
    .....
    mLooper = Looper.myLooper();
    .....
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

 

從第二個方法裡面可以看出,建立一個handler對象,主要是使其final MessageQueue mQueue範圍指向一個對象,其它的範圍用預設的都行。mQueue來自mLooper = Looper.myLooper();看下myLooper()方法的實現:

[java]
<SPAN style="COLOR: #993300">public static Looper myLooper() {  
    return sThreadLocal.get();  
}  
// sThreadLocal.get() will return null unless you've called prepare().   
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();</SPAN> 

public static Looper myLooper() {
    return sThreadLocal.get();
}
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

 


     到這裡是時候說明下ThreadLocal了,ThreadLocal是java中為每個線程都提供一個變數值的副本,是Java中一種較為特殊的線程綁定機制。這裡我們只要記住以下幾點:1.每個線程中獲得的ThreadLocal的值都是線程獨立的,和其它線程沒有關聯。2.對於ThreadLocal的理解在記住第一點的基礎上只需要記住public void set(T)和public T get()兩個介面就可以。
        事實上android利用ThreadLocal,為每個UI線程建立一個looper對象,每個looper對象有一個訊息佇列MessageQueue。每次聲明一個handler,其主要步驟就是綁定當前線程的訊息佇列,這之後就可以利用handler將需要的操作派發到訊息佇列中。一般在每個線程的開始執行Looper.prepare();這是為當前線程建立線程私人的looper對象,這之後就可以聲明handler;一般在每個線程的最後執行Looper.loop();前面說明handler綁定了當前線程的訊息佇列,loop()方法就是監聽訊息佇列,並且執行操作,因此這個方法是一個無限迴圈,其之後的代碼都不會執行,所以線上程的最後執行。
        這種模式有點像大學作業系統中的生產者和消費者模式,looper就像消費者,handler就像生產者,比較特殊的是在一個線程中消費者looper只能有一個,生產者handler可以有多個。接下來帶著上面的知識看看looper中的主要代碼:

[java] 
<SPAN style="COLOR: #993300">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)); 

public static void loop() { 
    final Looper me = myLooper(); 
    final MessageQueue queue = me.mQueue; 
    for (;;) { 
        Message msg = queue.next(); // might block  
        ..... 
        msg.target.dispatchMessage(msg); 
    } 
}</SPAN> 

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));
}
public static void loop() {
    final Looper me = myLooper();
    final MessageQueue queue = me.mQueue;
    for (;;) {
        Message msg = queue.next(); // might block
        .....
        msg.target.dispatchMessage(msg);
    }
}

 

在程式中如果某一個子方法裡面涉及到了handler而當前線程沒有綁定looper(比如在某個自己建立的線程中新分配的一個對象就可能需要handler),運行時就會拋出異常:

[java] 
<SPAN style="COLOR: #993300">if (mLooper == null) { 
    throw new RuntimeException( 
        "Can't create handler inside thread that has not called Looper.prepare()"); 
}</SPAN> 

if (mLooper == null) {
    throw new RuntimeException(
        "Can't create handler inside thread that has not called Looper.prepare()");
}

 

而如果只線上程的開頭執行Looper.prepare();而沒有執行Looper.loop();就會出現很多操作不會執行的現象。

     


 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.