注:此blog仅学习记录所用,如有不对的地方请大路大牛指点改正,不喜的请轻喷!
Handler实现线程间通讯,是因为共享了looper的内存,所以handlerMessage()运行在哪个线程由looper决定。而在new handler时默认使用的是主线程的looper,因此运行在主线程。
主线程创建时,消息队列和looper对象就会被创建;主线程中有一个消息轮询器looper,不断检测消息队列中是否有新消息,如果发现有新消息,自动调用此方法是在主线程中运行的;
handler为什么必须在UI线程创建?
可以先查看下handler的源码
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());
}
}
// 获取到Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 获取都消息队列
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
/**
* 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();
}
由 sThreadLocal.get 继续探入
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));
}
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
在prepareMainLooper()方法中,调用了prepare()方法中创建了一个Looper并且和sThreadLocal关联起来sThreadLocal.set(new Looper(quitAllowed)),通过这一步骤消息就和线程关联起来,不同线程质检就不能彼此访问对方的消息队列了。消息队列通过Looper和线程关联起来,而Handler又和Looper关联起来,如果我们单独开一个子线程的时候,由于没有创建Looper,所以在创建Handler的时候会抛出异常。
如果在子线程中new Handler()时会报错,如果需要在子线程中new Handler()需要先调用 Looper.myLooper(); 方法,具体实现代码如下:
class myThread extends Thread{
public Handler mHandler;
public Looper mLooper;
@Override
public void run() {
super.run();
Looper.prepare();
mLooper = Looper.myLooper();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("" + Thread.currentThread());
}
};
Looper.loop();
}
}
总结:Handler一般就是用于主线程跟子线程之间的通信。比如,子线程不能更新UI,那么通过handler的sendMessage( )发送消息给主线程,而主线程在创建时,Message Queue(消息队列)和looper(轮询器对象)就会被创建,message就会放在Message Queue里,而Looper一旦发现Message Queue中有消息,就会把消息取出,然后把消息扔给Handler对象,Handler会调用自己的handleMessage方法来处理这条消息。