Handler机制:用于在工作线程与UI线程之间进行消息传递的机制。(因为工作线程不能直接操作UI组件的属性值)
- Handler的作用:
1) 在新启动的线程(非UI线程)中发送消息。
2) 在主线程(UI线程)中获取消息、处理并完成UI组件的操作。 - Handler使用步骤:
1) 在主线程(UI线程)中创建Handler的子类对象,并重写处理消息的回调方法。
2) 在新启动的线程(非UI线程)中创建消息,并发送。
3.Handler原理:Android系统在启动一个Activity界面时,会为它创建一个消息循环(Looper)和消息队列(MessageQueue)。
1) Looper:消息循环(轮询器),负责从MessageQueue中取出消息(Message),并将消息分发到发送该消息的Handler对象
2) MessageQueue:用FIFO方式管理消息的消息队列。
3) Handler:负责把消息发送给Looper管理的MessageQueue,并负责处理Looper分发过来的消息。
prapare()方法:保证每个线程最多只有一个Looper对象。
looper()方法:启动Looper,使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给对应的Handler进行处理。
Looper实现原理
Looper类里包含一个消息队列对象和一个线程对象。当创建Looper时,会自动创建一个消息队列,同时将内部线程对象指向创建Looper的线程。当开启Looper后(looper.loop()),会自动进入无限for循环中,不断去遍历消息队列,如果没有消息则阻塞,有消息则回调handler的handlemessage方法进行处理。
Looper.prepare()
首先,要使用Looper机制一般会在当前线程中创建Handler对象,里面会自动创建一个looper对象和消息队列,这里面的消息队列属于当前线程空间。但此时的looper还不会去遍历,也没有绑定到当前线程。其中,looper对象内部也包含一个空消息队列对象和空线程。通过Looper.prepare()方法,先让该消息队列指向当前线程的消息队列,让空线程也指向当前线程。从而实现了绑定。
如何在子线程中使用Handler:
Handler本质是从当前的线程中获取到Looper来监听和操作MessageQueue,当其他线程执行完成后回调当前线程。
子线程需要先prepare()才能获取到Looper的,是因为在子线程只是一个普通的线程,其ThreadLoacl中没有设置过Looper,所以会抛出异常,而在Looper的prepare()方法中sThreadLocal.set(new Looper())是设置了Looper的。
class Rub implements Runnable {
public Handler myHandler;
// 实现Runnable接口的线程体
@Override
public void run() {
/*①、调用Looper的prepare()方法为当前线程创建Looper对象并,
创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue*/
Looper.prepare();
/*.②、创建Handler子类的实例,重写HandleMessage()方法,该方法处理除当前线程以外线程的消息*/
myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String ms = "";
if (msg.what == 1) {
}
}
};
//③、调用Looper的loop()方法来启动Looper让消息队列转动起来
Looper.loop();
}
}
创建线程的两种方式:
- 创建一个Thread对象(继承Thread类,重写run方法)
- 创建一个Runnable对象(实现Runnable接口,重写run方法),以这个对象来构造Thread对象。
另外除了发送消息之外,我们还有以下几种方法可以在子线程中进行UI操作:
- Handler的post()方法
- View的post()方法
- Activity的runOnUiThread()方法