说实话我感觉这标题起的有点怪,但我真不知道该怎么去表达好,总之这篇小短文就是告诉你,Handler到底是在哪个线程中处理消息的。
这几天在复习Handler,看了许多博客,有的说Handler是在创建实例的线程中处理消息的,有的说是在关联的looper线程中处理的。看了这么多,不如自己写个程序测一下就知道了。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//新线程
new Thread(){
@Override
public void run(){
Looper.prepare();
//子线程中创建Handler实例
Handler handler;
handler = new Handler(getMainLooper()){
@Override
public void handleMessage(Message msg){
Log.e("currentThread",Thread.currentThread().getName()+
new Date(System.currentTimeMillis()));
}
};
handler.sendEmptyMessage(1);
Log.d("currentThread",Thread.currentThread().getName()+
new Date(System.currentTimeMillis()));
Looper.loop();
}
}.start();
}
可以看到我们在主线程中开启了一个新的子线程,并在子线程中创建了Handler实例,但是我们用 getMainLooper() 将它与主线程的Looper绑定,然后在消息处理中我们打印当前线程。同时我们在该子线程中也打印当前线程的名称。特地用Logd和Loge是为了更容易区分,一个红色一个白色怎么样都不会搞错嘛是吧。好我们现在跑一下看看
D/currentThread: Thread-4 我是子线程
E/currentThread: main 我是handler
第一行是白色的,第二行是红色的,不知道你们有没有看出来,反正我看出来了(
结果很明显,Handler与主线程Looper绑定,而结果也确实是在主线程打印的,因此 Handler并不是在创建实例的线程中处理消息,而是在绑定的Looper线程中处理消息的。 那么为什么会有人错以为是在创建实例的线程中处理消息的呢?我们看一下源码就知道了
public Handler() {
this(null, false);
}
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());
}
}
//在这里!很关键!构造时默认将Handler的looer对象与当前线程的绑定了。
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;
}
关于Handler的文章遍地都是,如果对它的机制还不是很了解的话,百度一下你就知道。这里推荐一下几篇大神的文章Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 和 android的消息处理机制(图+源码分析)——Looper,Handler,Message
这篇博客只是用来作为我的学习过程中的一点小笔记,如果对你也有帮助的话我也很高兴。