多线程—Handler
1 说在头里
之前看到一段话,感觉很有用,这里引用一下。
Handler并不是专门用来更新UI的,只是开发者常常用它来更新UI。Handler的主要用于同一个进程间的线程通信,Handler用于更新UI的时候是"子线程与主线程通信";当然,Handler也可以用于子线程之间通信。Handler的消息机制主要是就指“Handler的运行机制”,Handler的运行机制时需要底层的MessageQueue和Looper支持的。
改短摘自链接:https://www.jianshu.com/p/f1da1ed7bd7e
2 Handler的使用
还是先说说这个东西咋用吧,分三步走,上栗子。
- 在主线程创建handler,重写handleMessage方法
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int arg1=msg.arg1;
if (msg.what==0x1234){
textView.setText(arg1);
}
}
};
- 在子线程中使用handler对象发送消息
Message message=handler.obtainMessage();
message.what=0x1234;
message.arg1=10086;
handler.sendMessage(message);
- 主线程中handler捕获消息,回调handleMessage对其进行处理
说到Handler,肯定是离不开Looper、MessageQueue、Message的。这几位大哥之间的关系很是亲密,下面有必要八卦一下。
3 Looper、MessageQueue、Message
先说说Looper,每一个线程最多只能有一个Looper。主线程中ActivityThread默认会把Looper初始化好,无需我们再建。但如果想要在子线程中创建一个Handler,那就要我们提前手工制作一个Looper了。制作方法很简单,只需调用静态方法prepare()即可
Looper.prepare();
Handler handler = new Handler() {
// 我懒了....
}
Looper.loop();
它的特点是它跟它的线程是绑定的,处理消息也是在Looper所在的线程去处理,所以当我们在主线程创建Handler时,它就会跟主线程唯一的Looper绑定,从而我们使用Handler在子线程发消息时,最终也是在主线程处理,达到了异步的效果。
来自 https://www.cnblogs.com/ryanleee/p/8204450.html
线程在初始化Looper时,会自动创建一个MessageQueue对象。
MessageQueue是一个消息队列,用来存放Handler发送的消息。MessageQueue通常都是由Looper来管理,MessageQueue大哥是跟着Looper大哥大混饭的,Looper上了,不用招呼MessageQueue立马就上(Looper创建时,自动创建一个MessageQueue)。Looper维护MessageQueue消息队列,该消息队列用来存放Handler发送的Message。
Message 消息对象,就是MessageQueue里面存放的对象。MessageQueue大哥可以收纳多个Message小弟。这个小弟的作用自然就是通风报信了(可以说是消息的载体),Handler会派出来一个Message,Message先到MessageQueue大哥处报道,Looper大哥大巡视时,提取Message问话。(Looper从MessageQueue中提取Message,并有Handlee的handleMessage()方法处理)
当我们需要发送一个Message时,我们一般不建议使用new Message()的形式来创建,更推荐使用Message.obtain()来获取Message实例,因为在Message类里面定义了一个消息池,当消息池里存在未使用的消息时,便返回,如果没有未使用的消息,则通过new的方式创建返回,所以使用Message.obtain()的方式来获取实例可以大大减少当有大量Message对象而产生的垃圾回收问题。
来自 https://www.cnblogs.com/ryanleee/p/8204450.html
4 Handler使用总结
Handler有两种方式去执行一些UI相关操作:
- Handler.sendMessage()
- Handler.post()
- 使用sendMessage()发送消息
//定义MyHandler类,并重写handleMessage()方法
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//执行某些操作,可更新UI
}
}
//主线程中创建MyHandler的实例
private MyHandler myhandler = new MyHandler();
//在子线程中创建需要发送的消息对象,Hander发送消息到消息队列
Message msg = Message.obtain();
msg.what = 1;
myhandler .sendMessage(msg);
- 使用Handler.post()方法
//主线程中先创建Handler实例
private Handler handler = new Handler();
//在子线程中使用Handler.post()
handler.post(new Runnable() {
@Override
public void run() {
//可以执行一些UI相关操作
}
});
可以看出,第二种方式比较灵活,无需定义Handler子类重写handleMessage()方法,只需要在子线程中使用主线程中创建的Handler对象,在子线程中调用Handler对象的post()方法即可。