剛開始學習Android的時候,知道異步線程沒法更新UI,因而找了個能把更新的動做拋給UI線程的東西,這個東西就是Handler。併發
一開始就只會在主線程也就是UI線程new一個Handler,以後在各個子線程裏面使用,並沒想過一些原理的東西,其實須要學習的知識還有不少。異步
1、線程之間的同步ide
A. 子線程向主線程發送消息,咱們一開始學習的都是這種比較簡單方式。oop
一、主線程中new Handler,並實現handleMessage方法post
二、子線程中得到主線程Handler的實例學習
三、子線程向主線程發消息sendMessageui
B. 主線程向子線程發送消息:this
#點擊按鈕向mThread線程發送消息
mStartBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ...... mHandler.sendMessage(......); } }); mThread.start(); ...... Thread mThread = new Thread(new Runnable() { @Override public void run() { Looper.prepare(); #實例化Handler,實現handleMessage mHandler = new Handler(){ @Override public void handleMessage(Message msg) { ...... } }; Looper.loop(); } });
經過這個咱們比較直觀的看見相同和不一樣的地方:spa
相同的地方:A線程向B線程發送消息,A須要拿到B實例化的Handler對象線程
不一樣的地方:子線程多了下面兩個東西:
Looper.prepare();
.......
Looper.loop();
其實說不一樣的地方,其實只是咱們實現的時候不須要寫Looper,可是主線程同樣須要有Looper,那麼很容易想到,Android已經給咱們寫好了,後面有具體講。
2、Looper,Handler,Message
Looper:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } 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)); }
Looper在建立的時候會初始化一個MessageQueue,這個是用來存儲Message的管道
public static void loop() {
final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; ...... for (;;) { Message msg = queue.next(); // might block ...... final long end; try { msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } ...... } }
在loop的時候會循環的從MessageQueue取Message,而後分發Message。msg.target其實就是Handler,因而Handler就能夠得到數據並進行處理。
public void dispatchMessage(Message msg) {
if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { message.callback.run(); }
上面的仍是比較有意思的,這裏簡單總結下:
通常的是3這種狀況,1發生在使用Handler在異步線程中直接更新UI的狀況。
Thread mThread = new Thread(new Runnable() {
@Override
public void run() { mHandler.post(new Runnable() { @Override public void run() { textView.setText("xxxx"); } }); } });
其實mHandler.post也是發送了一個消息,而後把Runnable傳給Message並處理。
總結下:
Looper其實就是建立一個循環獲取消息併發送Handler的類。
Message其實就是一個數據存儲的類,用於傳輸數據。
Handler就是進行發送和介紹處理的類。
這三個配合起來一塊兒用,才能構建了handler線程之間傳遞數據的機制。
問題一:上面所說的須要Looper,Handler,Message配合使用才能完成這個工做,那麼我寫子線程向主線程時怎麼沒看到主線程的Looper呢?
這個咱們能夠去看下Activity的源碼,其實在ActivityThread裏面已經寫好了這個東西,全部咱們不須要寫了。
public static void main(String[] args) {
......
Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); ...... Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
注意:寫在Looper.loop();後面的代碼是沒法執行。