最近一直在學習多線程,handler的作用真的很重要啊,所以保存這篇看的蠻懂的。
Handler mHandler = new Handler(); mHandler.post(new Runnable() { @Override public void run() { showContentView(contentView); } });
下面我們先來看一下這個方法是怎么執行的
首先:
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
它把Runnable重新封裝了一遍然后調用了sendMessageDelayed方法
看一下是怎么封裝的
private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
看到了吧,用過Handler的都知道Message是用來記錄信息的最小單元,這里把Runnable封裝到一個Message對象並返回
然后:
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
這里就是對delayMillis做了一下有效性檢測
緊接着:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
Handler對象把Message壓到了MessageQueue隊列里面
貌似方法到這里就return了,那么壓進去的信息是怎么發送的呢? 這得從Handler的原理說起了。有很多人已經寫了這個原理了,就不在做闡述
可以查看這篇博客《android handler線程原理詳詳解》
然后我們去分發信息的點去看是如何執行的
public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } }
Looper對象把MessageQueue里面的Message逐個取出來,注意看msg.target.dispatchMessage(msg)這一句。
Message類定義了一個字段target,這個字段就是Handler類型,存的對象就是創建這個message的對象,也就是我們的handler對象。
然后就是調用我們的handler里面的dispatchMessage(msg)方法了
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
看到沒有,一開始我們的Runnable傳進來,然后調用GetPostMessage方法把Runnable賦值給了Massage里面的callback,
在分發的時候判斷如果callback不是null就調用handleCallback(msg)方法。
最后,執行我們的線程。
private final void handleCallback(Message message) { message.callback.run(); }
---------------------------------------------------------小小分割線----------------------------------------------------------
意義:
到了這里,我們發現貌似這玩意也就是轉了一圈又調用了線程的run而已么,那么這又有什么用呢。
如果我們給handler傳入的是一個message,那么最后會調用我們的handler的handleMessage(Message)方法,然后我們再去判斷最后再去處理
,但是我們用runnable可以直接傳入如何操作的對象,不需要再接收到消息后再去判斷message的what然后選擇做什么操作,從代碼清晰的角度,
我也覺得這樣子會比在判斷一遍要清晰,容易理解很多。
---------------------------------------------------------小小分割線----------------------------------------------------------
所解決的問題:
請看博文第一段代碼,這里面的runnable執行了一個setContentView(View),這里的handler是在onActivityResult里面調用的,也就是注銷后重新登錄回到主頁面的這種情況,這個view里面包含了一些fragment,然后activity里面綁定fragment是需要是活動狀態的,如果不用handler,直接執行,在onActivityResult方法執行期間activity還是在onPause狀態,所以在程序執行到添加fragment的時候報錯了,而用了handler就能保證這段代碼最后會在activity處於活動狀態既UI線程里面執行了。
原文鏈接:http://blog.csdn.net/panjidong_3/article/details/7890383