Android的訊息處理(Handler相關)

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   os   io   使用   ar   

  首先Message(訊息)類不用多說,內部用what(啥)屬性來存放標識符,用obj(對象)來存放要攜帶的資料,用target(目標)來存放目標Handler。

  所以需要有一個Handler(控制代碼)類來處理Message,方法是調用Handler類中的sendMessage(Message)方法,我之前一直覺得這個方法名的邏輯很奇怪,現在懂了,因為知道了另一個類:

  MessageQueue(訊息佇列),在調用sendMessage之後Handler會依次調用兩個不是重載但跟重載也差不多的內部方法,最後像這樣

sent = queue.enqueueMessage(msg, uptimeMillis);

把Message發送(send)給內部建立的一個MessageQueue對象,同時把Message中的target屬性設定為自己。

  這時又要說到另一個類,Looper(迴圈器)。程式啟動並執行時候安卓會在主線程裡建立一個Looper,

 1     /** 2      * Initialize the current thread as a looper, marking it as an 3      * application‘s main looper. The main looper for your application 4      * is created by the Android environment, so you should never need 5      * to call this function yourself.  See also: {@link #prepare()} 6      */ 7     public static void prepareMainLooper() { 8         prepare(false); 9         synchronized (Looper.class) {10             if (sMainLooper != null) {11                 throw new IllegalStateException("The main Looper has already been prepared.");12             }13             sMainLooper = myLooper();14         }15     }
系統調用

它以for死迴圈的方式不斷嘗試從隊列中取出Message,

Message msg = queue.next();

取到了就調用這個Message中的target中存放的那個Handler的dispatchMessage(Message)方法。像這樣:

msg.target.dispatchMessage(msg);

  Handler用這個方法稍微進行一下判斷,之後就轉交給自己的handleMessage(Message)方法來處理訊息,這個方法和onCreate一樣是由程式員重寫,由系統調用的。

  剩下的就很簡單了,handleMessage方法是程式員自己寫的,想做點什麼都行。

  通常是根據Message中的what來switch一下,對於不同訊息來源做出不同反應就可以啦。

 

 

 

那麼總結一下:

  明面上程式員做兩件事。

  首先是建立Handler,重寫好方法,決定用它來做點什麼;

  後面的分為兩種情況。

  如果調用Handler的時候需要攜帶資訊,就用Message.obtain()方法或new關鍵字得到Message對象,然後使用Handler對象的sendMessage(Message)方法交由Handler處理。

  如果並不需要攜帶額外資訊,只需要通知Handler有事要做,就不需要自己得到Message對象,直接使用Handler對象的sendEmptyMessage(int)方法,Handler會像這樣

Message msg = Message.obtain();msg.what = what;

自己建立一個Message對象,並用方法中傳入的int值作為Message的what屬性。

         第一步,定義Handler。

         第二步,發送訊息。

         這樣。

 

 

PS:

  如果要在主線程之外使用Handler要注意一個問題。

  首先按照上面說的,訊息是由Looper從隊列中取出並分發的,只管自己的線程。可是主線程中使用的Looper是安卓系統建立的,使用者建立線程的時候並不會自動建立一個新的Looper,所以Looper告訴你

final Looper me = myLooper();if (me == null) {     throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");}

這個,Handler告訴你

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

這個。

  因此,要在新線程裡建立Handler就需要調用Looper.prepare()方法來準備好一個Looper,這個方法會自動調用內部的重載方法,不需要擔心。

    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));    }

  自己調用的時候參數是true,系統調用的時候是false,總之不需要在意。

 

 

  Handler用來讓其他線程修改UI啊,這個不用我說吧。

Android的訊息處理(Handler相關)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.