Looper:循環器,是一個用於使線程運行一個消息(Message)循環的類。線程默認沒有關聯的消息循環,在建立它以前,在將要運行循環的線程中調用prepare方法,而後loop方法會處理消息直到循環結束。 java
絕大多數消息循環是經過Handler類來Looper交互的。 ide
下面是實現了Looper的線程的一個典型例子,使用分離的prepare方法和loop方法來建立一個用於跟Looper溝通的初始Handler。 oop
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(); } }
先看準備工做的prepare方法: ui
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }
每條線程只能綁定一個Looper,不然會拋出RuntimeException異常。若是不調用prepare方法,sThreadLocal.get()就會返回null。注意這是個靜態方法,在最後一行中綁定了一個作爲Looper的線程。怎麼綁定的呢,看看Looper的一個私有無參構造方法: spa
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }
構造方法裏初始化了一個消息隊列、一個運行狀態的標誌以及綁定一個線程(建立者所在的線程)。prepare方法給了一個在真正的循環開始以前,參照Looper建立一個Handler的機會。注意:在run方法中初始化Handler以前,必須調用Looper.prepare(),否則會拋出一個運行時異常,由於Handler須要一個從Looper獲得的消息隊列(即構造方法裏面的mQueue)。調用prepare方法後必定要調用loop方法,而且調用quit方法退出循環。 線程
接下來,看看在當前線程裏運行一個消息隊列的loop方法,用完後必定要調用quit方法結束循環: code
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) { // No target is a magic identifier for the quit message. return; } msg.target.dispatchMessage(msg); msg.recycle(); } } }
高潮來了,上面說過,Looper的mQueue是Handler使用的消息隊列,loop方法啓動一個死循環從隊列中獲取數據,當隊列中沒有數據時,queue.next()會阻塞。當有數據時,msg.target(即Handler)就會調用dispatchMessage方法,進而調用Handler的handleCallback或者handlerMessage方法。從這些也能夠知道,若是Handler是在子線程的run方法中建立(以前必須調用Looper.prepare())的,那麼這個Handler的handleMessage或者handleCallback方法就是運行在子線程的。 隊列