Hanlder機制用於線程間通訊,一般用於子線程給主線程發送消息更新UIandroid
Handler
Message的主要處理者,用於發送消息,接收處理消息
Message
消息,線程間通訊的數據單元
MessageQueue
消息隊列,用於存放消息,取出消息
Looper
循環器,Message和Handler的橋樑,循環取出MessageQueue的消息發送Handleride
須要注意幾點:oop
在建立Handler以前,須要調用Looper.prepare()方法,之因此日常使用未調用過,是由於android在程序啓動時幫咱們建立好了,具體代碼在activityThread中的main()方法中,post
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter()); final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper();//在此調用的Looper.prepare() ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
所以咱們在子線程使用Handler的時候,須要調用Looper.prepare()方法ui
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
調用Looper.prepare()方法後只能確保在建立Handler的時候不報錯,若是不調用Looper.loop()方法,則沒有任何效果,一樣,android在程序啓動時,已經爲咱們作好了這一步this
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter()); final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper();//在此調用的Looper.prepare() ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop();//在此調用的Looper.loop() throw new RuntimeException("Main thread loop unexpectedly exited"); }
Handler的工做原理spa
當咱們啓動程序的時候,android自動在ActivityThread中幫咱們建立了Looper.prepare()方法,建立了Looper對象.
在調用Looper.prepare()方法時,會建立Looper對象,當前線程會將Looper的對象保存,而且在Looper構造方法中,建立MessageQueue對象,也就是說一個Looper一個MessageQueue線程
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)); } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
Handler調用postMessage之類的方法,最後都會調用sendMessageAtTime()方法,其中有queue.equeueMessage(msg)方法,實際就是消息入列邏輯code
public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; //該方法爲將消息添加到MessageQueue sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } synchronized (this) { 10 9 if (mQuiting) { RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } //將消息的時間傳進來賦給Message msg.when = when; Message p = mMessages; 0 if (p == null || when == 0 || when < p.when) { msg.next = p; 1 //將要取出的消息 mMessages = msg; 0 this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } } return true; }
由上面咱們能夠得知,其實MessageQueue並無用集合將消息存儲起來,而是mMessages對象表示當前待處理的消息,所謂的加入隊列其實就是將全部的消息按時間進行排序,具體的操做就是根據Message的時間,去調用msg.next。
從消息取出消息隊列是經過Looper.loop(),其實是一個死循環,不斷調用MessageQueue.next方法,他其中的操做就是判斷當前是否有須要處理的消息,若是有,則取出來,將下個消息成爲mMessages,不然就進入阻塞狀態,一直等待新消息的加入。對象
public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { 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.loop()方法中找到將要處理的消息後,會調用msg.target.disPatcheMessage()方法,msg.target就是Handler.也就是調用了Handler.disPatchMessage()方法,在這個方法中,會判斷mCallBack是否爲空,若是不爲空調用callback,若是爲空,則調用了handlerMessage()方法,至此整個消息處理完成
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
對於上條的mCallBack,是由於在建立Handler對象的時候能夠傳入一個CallBack對象,若是return true,下面的handlermessage就不會收到消息,反正則能收到消息
private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //返回爲true則下面的handlerMessage不能收到消息 //返回false則下面的hanlderMessage可以收到消息 return false; } }){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } };