首先需要先理清 Handler、MessageQueue、Looper 之間的關係。
我們使用Handler的時候(UI主線程)一般是通過以下兩種方法去創建一個Handler實例
1. 最常用的方法:方法1
Handler mHandler =new Handler(){
@override
public void handleMessage(Message msg){
//To Do Something
}
}
mHandler.sendMessage(msg);//發送消息
去看一下Handler的無參構造方法是怎麼創建Handler實例的
/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*/
public Handler() {
this(null, false);
}
無參構造方法裏調用了另外一個構造方法,繼續看下面的源碼
/**
* Use the {@link Looper} for the current thread with the specified callback interface
* and set whether the handler should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
重點看下面兩句
mQueue = mLooper.mQueue;//將Looper的mQueue賦值給mHandler的 mQueue
在Handler的構造方法裏面直接通過Looper的myLooper()方法初始化自己的mLooper,我們進入該方法
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
//下面是Looper中的靜態變量 sThreadLocal 的定義
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
通過myLooper()方法的註釋也可以知道,該方法返回的是當前線程的 Looper (注意:一個線程對應唯一的一個Looper)
但是怎麼來獲取當前的線程呢,進入ThreadLocal的get()方法就知道了
/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();//通過這句代碼獲取到當前的線程
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
現在我們應該明白了當我們通過方法1創建一個Handler實例的時候,在Handler的構造方法裏會爲我們獲取當前線程的
Looper,並且將該Looper的MessageQueue對象的引用mQueue賦值給Handler的mQueue。所以我們通過Handler的se-
ndMessage()方法發送消息的時候自然也就發送到了該Handler所在線程的Looper所管理的MessageQueue消息隊列中。
所以下面這句代碼就是發送到了mHandler所在線程(UI線程)的Looper所管理的MessageQueue隊列中
mHandler.sendMessage(msg);
2. 還有一種使用Handler的方法:方法2
這裏我們採用了 IntentService 中的例子
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
重點關注以下代碼:
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
在IntentService中自定義了一個Handler ServiceHandler ,在 new 一個Handler實例的時候,傳入了一個參數mServiceLooper
這個Looper是哪裏來的呢,代碼裏是通過HandlerThread的getLooper()方法獲取,如果你去看HandlerThread的源碼,就會發
現它其實也是通過Looper的myLooper()方法獲取到的 HandlerThread 所在線程所對應的那個Looper。
ServiceHandler的構造方法直接調用了父類的構造方法:super(looper),也就是 Handler 的構造方法
接下來我們再去看一下 Handler 的另一個構造函數
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public Handler(Looper looper) {
this(looper, null, false);
}
可以看到,該構造方法又調用了Handler的另一個構造方法:
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
這裏依然是和方法1中的構造方法一樣的操作,將傳入的serviceLooper 最終賦值給了 Handler的mLooper(同時也是子類ServiceHandler的mLooper),再將該Looper對應的 mQueue 賦值給了 Handler 的mQueue(同時也是子類ServiceHandler的mQueue)