標籤:
流程總結
- Looper.prepare():本線程中儲存一個Looper執行個體,然後該執行個體中儲存一個MessageQueue對象;因為Looper.prepare()在一個線程中只能調用一次,所以MessageQueue在一個線程中只會存在一個。
- Looper.loop():輪詢MessageQueue,回調msg.target.dispatchMessage(msg)方法。
- Handler構造方法:得到當前線程中儲存的Looper執行個體,進而與Looper執行個體中的MessageQueue想關聯。
- Handler的sendMessage():會給msg的target賦值為handler自身,然後加入MessageQueue中。
- 重寫handleMessage():是msg.target.dispatchMessage(msg)最終調用的方法。
Tip:在Activity的啟動代碼中,已經在當前UI線程調用了Looper.prepare()和Looper.loop()方法。建立handler就不用顯示的調用Looper.prepare()和Looper.loop()
觀察者模式
Looper
建立一個MessageQueue,輪詢MessageQueue
- 構造方法
- prepare()
- loop()
- looper方法必須在prepare方法之後運行
- 輪詢,無 -> 阻塞,有 -> msg.target.dispatchMessage(msg);
- 作用
- 綁定當前線程,有且只有一個looper執行個體和MessageQueue,輪詢並通知
handler
訊息建立者,非同步分發
public Handler() { this(null, false); } public Handler(Callback callback, boolean async) { 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 = callback; mAsynchronous = async; }
- mLooper = Looper.myLooper(); 擷取looper
- mQueue = mLooper.mQueue;擷取messagequeue
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
- msg.target = this; => msg.target.dispatchMessage(msg); handler發出的訊息,最終會儲存到訊息佇列中去
MessagedispathMessage
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
因為訊息的最終回調是由我們控制的,我們在建立handler的時候都是複寫handleMessage方法,然後根據msg.what進行訊息處理
private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case value: break; default: break; } }; };
- public int what:變數,用於定義此Message屬於何種操作
- public Object obj:變數,用於定義此Message傳遞的資訊資料,通過它傳遞資訊
- public int arg1:變數,傳遞一些整型資料時使用
- public int arg2:變數,傳遞一些整型資料時使用
- public Handler getTarget():普通方法,取得操作此訊息的Handler對象。
完成調度資訊
- {@link #post}, {@link #postAtTime(Runnable, long)},
- {@link #postDelayed}, {@link #sendEmptyMessage},
- {@link #sendMessage}, {@link #sendMessageAtTime}, and
- {@link #sendMessageDelayed} methods. The <em>post</em> versions allow
Handler post
mHandler.post(new Runnable() { @Override public void run() { Log.e("TAG", Thread.currentThread().getName()); mTxt.setText("yoxi"); } });
Runnable並沒有建立什麼線程,而是發送了一條訊息
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } 在getPostMessage中,得到了一個Message對象,然後將我們建立的Runable對象作為callback屬性,賦值給了此message.
註:
- 產生一個Message對象,可以new ,也可以使用Message.obtain()
- Message內部維護了一個Message池用於Message的複用,使用Message.obtain()方法避免使用new 重新分配記憶體。
- 如果你的message只需要攜帶簡單的int資訊,請優先使用Message.arg1和Message.arg2來傳遞資訊,這比用Bundle更省記憶體
- 擅用message.what來標識資訊,以便用不同方式處理message
如果不為null,則執行callback回調,也就是我們的Runnable對象。
問題
1,使用Handler 是非同步,它會建立新的線程嗎? 不會
2,Handler 是在主線程內嗎? 一般都會在主線程內,但也可以在子線程中建立Handler
3,Handler 的 post 和 sendMessage 方法,使用的是一個隊列不安是兩個? 一個
4,子線程中建立一個 handler, 然後sendMessage 會怎麼樣? 會崩潰
5,子線程建立 handler ,構造的時候舒心入主線程的 Looper ? yes
android handler機制源碼解析【非同步回調】