1、在子线程中,如果要使用Handler,则先调用Looper.prepare() 为线程开启一个消息循环,最后再调用loop() 方法使之处理信息,直到循环结束。
主线程的话,主线程系统会自动为其创建Looper对象,开启消息循环。
Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。 然后通过Looper.loop() 让Looper开始工作,从消息队列里取消息,处理消息。
写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。
例:
class
MyThread1
extends
Thread {
@Override
public
void
run() {
super
.run();
Looper.prepare();//有该函数,下面的Handler才会起作用,否则下面的Handler不会工作
handler1 =
new
Handler(){
@Override
public
void
handleMessage(Message msg) {
super
.handleMessage(msg);
System.out.println(
"threadName--"
+ Thread.currentThread().getName() +
"messageWhat-"
+ msg.what );
}
};
handler2.sendEmptyMessage(
2
) ;
Looper.loop(); //处理事件
}
}
class
MyThread2
extends
Thread {
@Override
public
void
run() {
super
.run();
Looper.prepare();
//有该函数,下面的Handler才会起作用,否则下面的Handler不会工作
handler2 =
new
Handler(){
@Override
public
void
handleMessage(Message msg) {
super
.handleMessage(msg);
System.out.println(
"threadName--"
+ Thread.currentThread().getName() +
"messageWhat-"
+ msg.what );
}
};
handler1.sendEmptyMessage(
5
) ;
Looper.loop();
}
}
以上函数,先执行
handler2.sendEmptyMessage(
2
) ;最后执行
handler1.sendEmptyMessage(
5
) ;因为有
Looper.prepare(),Handler才会起作用。
2、Handler有几个构造重载,如果构造时没有提供Looper类对象参数,会获取当前线程的Looper对象,即将当前线程的消息循环作为Handler关联的消息循环。
3.
消息处理机制中,消息存放在一个消息队列中,而线程围绕这个队列进入一个无限循环,直到程序退出。
如果队列中有消息,线程就会把消息取出来,并分发给相应的Handler进行处理;
如果队列中没有消息,线程就会进入空闲等待状态,等待下一个消息的到来。
以上,对照看HandlerThread。
子线程处理,不需要写Looper.prepare()之类的。是一个内部建立了Looper的普通Thread。
HandlerThread将loop转到子线程中处理,分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。
但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。
用法:
1.先创建HandlerThread的对象:mThread = new HandlerThread("handler_thread");
2.再启动该线程:mThread.start();
3.创建运行在该线程中的Hadnler:
mHander = new Handler(mThread.getLooper()){
handlerMessage(){
..............................
}
};
5.如何退出该循环:用Looper的quit方法或quitSafely方法
Looper的quit方法时,实际上执行MessageQueue中的removeAllMessagesLocked方法,该方法的作用是把MessageQueue消息池中所有的消息全部清空,无论是延迟消息(延迟消息是指通过sendMessageDelayed或通过postDelayed等方法发送的需要延迟执行的消息)还是非延迟消息。
Looper的quitSafely方法时,实际上执行了MessageQueue中的removeAllFutureMessagesLocked方法,通过名字就可以看出,该方法只会清空MessageQueue消息池中所有的延迟消息,并将消息池中所有的非延迟消息派发出去让Handler去处理,quitSafely相比于quit方法安全之处在于清空消息之前会派发所有的非延迟消息。
无论是调用了quit方法还是quitSafely方法只会,Looper就不再接收新的消息。即在调用了Looper的quit或quitSafely方法之后,消息循环就终结了,这时候再通过Handler调用sendMessage或post等方法发送消息时均返回false,表示消息没有成功放入消息队列MessageQueue中,因为消息队列已经退出了。
需要注意的是Looper的quit方法从API Level 1就存在了,但是Looper的quitSafely方法从API Level 18才添加进来。
参考文章: