Andriod提供了 Handler 和 Looper 来满足线程间的通信。 Handler 先进先出原则。 Looper 类用来管理特定线程内对象之间的消息交换 (MessageExchange) 。
1)Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 MessageQueue( 消息队列 ) 和对消息进行循环。
2)Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息到 MessageQueue 里 ; 或者接收 Looper 从 Message Queue 取出 所送来的消息。
3) Message Queue( 消息队列 ): 用来存放线程放入的消息。
4) Message:是线程间通讯的消息载体。两个码头之间运输货物,Message充当集装箱的功能,里面可以存放任何你想传递的消息。
看到这里就明白了为什么:如果一个线程要处理消息,那么它必须拥有自己的Looper,并不是Handler在哪里创建,就可以在哪里处理消息。
Handler 必须要和 Looper 中结合使用,尤其在子线程中创建 Handler 的话,需要这样写:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
//此时handler会默认传入当前线程的lopper对象。
lopper是一个android封装的类,本质就是一个无限循环的线程。可以是子线程,也可以是主线程。
如下代码这表示这个消息队列要执行的任务是在子线程中完成。
//Handler handler = new Handler(getMainLooper());消息队列在主线程中控制。这是handler的消息处理是在UI线程中执行的。
mHandler = new Handler() {
public void handleMessage(Message msg) {
// 这里处理消息
}
};
Looper.loop();
如果此时另一个线程(主线程或者子线程)拿到该mHandler 执行
sendMessage(Message msg)
mHandler.post()方法。
则可以做到线程之间的通信。
}
不借助lopper也同样可以做的线程之间通信。
例如
1,使用wait方法。
2,循环监听
new Thread(new Runnable() { @Override public void run() { while (listener != null){ listener.do();//接口调用。另一个线程可以将接口赋值。这个现在来执行 } } });
可以看到,非常繁琐,一层套一层看着也不美观。
HandlerThread 就是为了帮我们免去写上面那样的代码而生的。
//1.初始化,参数为名字,也就是线程的名
mHandlerThread = new HandlerThread("WorkThread"); //必须调用start方法,因为HandlerThread继承自Thread来启动线程 mHandlerThread.start();
//初始化Handler,只是传递了一个mHandlerThread内部的一个looper
mHandler = new Handler(mHandlerThread.getLooper()) { //不能刷新页面,因为HandlerThread本身就是个字线程。
@Override public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("WorkThread", (Looper.getMainLooper() == Looper.myLooper()) + "," + msg.what);
}
};
HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。
但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。