Android系統(tǒng)中的視圖組件并不是線程安全的,如果要更新視圖箩退,必須在主線程中更新丑罪,不可以在子線程中執(zhí)行更新的操作。在子線程中通知主線程我們需要使用到handler對象杰扫。
//更新視圖
private Handler handler =new Handler() {
? ? @Override
? ? public void handleMessage(Message?msg)?{
? ? ? ? if(msg.what?==?COMPLETED)?{
? ? ? ? ? ? stateText.setText("completed");
? ? ? ? }
? ? }
};
只要在Thread中處理復(fù)雜的任務(wù)队寇,然后通過handler對象告知主線程,就可以解決線程安全問題章姓。這個過程中佳遣,消息機制起著重要的作用。Android通過Looper凡伊、Handler來實現(xiàn)消息循環(huán)機制零渐。Android的消息循環(huán)是針對線程的,每個線程都可以有自己的消息隊列和消息循環(huán)系忙。
Looper
Looper的作用是關(guān)聯(lián)起Thread和循環(huán)取出消息诵盼,Looper構(gòu)造方法是私有的,其中做了兩件事:創(chuàng)建一個MessageQueue與得到與之對應(yīng)的Thread银还。MainLooper是啟動Activity創(chuàng)建ActivityThread(并不是一個Thread)時候創(chuàng)建风宁,所以不能多次創(chuàng)建。一個線程對應(yīng)一個Looper對象蛹疯,通過ThreadLocal保證一個線程只有一個Looper與之對應(yīng)戒财,如果多次調(diào)用Looper.prepare()則會拋出運行時異常。
private static void prepare(boolean quitAllowed){
? ? if(sThreadLocal.get() !=null) {// 查看是否有l(wèi)ooper與當前線程對應(yīng) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?thrownewRuntimeException("Only one Looper may be created per thread");
? ? }?
? ? sThreadLocal.set(new Looper(quitAllowed));
}
當開啟一個loop后是一個死循環(huán)苍苞,從MessageQueue中取出消息固翰,處理消息狼纬,但是也有可能退出,在沒有消息后退出循環(huán)骂际。
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
? ? ? ? if(msg ==null) {// 當沒有消息的時候疗琉,退出
? ? ? ? ? ? // No message indicates that the message queue is quitting.
? ? ? ? ? ? return;
? ? ? ? }// 略
? ?msg.target.dispatchMessage(msg);
? }
Handler
Looper的作用是發(fā)送消息到MessageQueue和處理消息。一個Looper對應(yīng)一個Thread歉铝,一個Looper包含一個MessageQueue盈简。當我們創(chuàng)建Handler時就會從當前線程中取出與之對應(yīng)的Looper,然后再從Looper中取出MessageQueue太示。
public Handler(Callback callback, boolean async){
? ? // 略
? ? mLooper = Looper.myLooper();// 取出當前線程中的Looper
? ? if(mLooper ==null) {
? ? ? ? throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
? ? }
? ? mQueue = mLooper.mQueue;// 取出MessageQueue
? ? mCallback = callback;
? ? mAsynchronous =async;
}
public Handler(Looper looper, Callback callback, boolean async){
? ? ? ? mLooper = looper;
? ? ? ? mQueue = looper.mQueue;
? ? ? ? mCallback = callback;?
? ? ? ?mAsynchronous =async;
? ? }
Message
消息機制中的message是單鏈表結(jié)構(gòu)柠贤,作用是作為數(shù)據(jù)的載體傳遞。Message有一個成員變量类缤,他的類型正是Handler臼勉,當我們通過Handler去send一個Message時候最終都會為這個成員變量賦值為this,即當前的Handler餐弱。另為如果是通過Message.Obtain(),獲取的復(fù)用Message也會為其賦值宴霸。
private boolean enqueueMessage(MessageQueue queue, Message msg,long uptimeMillis){ ? ? ? ?msg.target =this;// 賦值語句
? ? if(mAsynchronous) {
? ? ? ? msg.setAsynchronous(true);
? ? }
? ? return queue.enqueueMessage(msg, uptimeMillis);
}
總結(jié)
通過一系列的包涵關(guān)系,最終Looper膏蚓、Handler瓢谢、Message、MessageQueue即發(fā)生關(guān)聯(lián)驮瞧,從而形成一個閉合氓扛,開啟消息循環(huán)。