引言:
- Android应用启动时,会默认有一个主线程(ui线程),在这个线程中会关联一个消息队列(MessageQueue),所有的操作都会被封装成消息(Message)然后交给主线程处理 ,为了保证主线程不会主动退出,会将消息的操作放在一个死循环中,这样程序就相当于一直在执行死循环,因此不会退出。
-
对于主线程来说,会自动绑定一个消息循环looper,查看源码,如图,主线程的消息循环在main方法(android程序的入口)中已经被创建。
ActivityThread.main方法执行完,应用程序就启动了,系统将消息投递到消息队列中,又会从消息队列中获取消息并且处理消息,而这一切Handler
起着重要的作用~
重点理解:
- 在主线程中创建,我们经常会遇到的一个问题就是更新ui,大家都应该知道在子线程是不能更新UI的,所以我们最常见的使用手段就是通过handler将消息send回主线程,handler再通过handleMessage方法在主线程进行处理。
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg){
//更新ui---主线程
}
}
MyHandler mHandler=new MyHandler();
//新线程
new Thread(){
public void run(){
//耗时操作
mHandler.sendEmptyMessage(123);
}
}.start();
- Handler就是一个消息处理器,将消息投递给消息队列,然后再由对应的线程从消息队列中逐个取出消息。
- 消息队列是通过Looper与线程关联
Handler的构造函数中获取looper,与looper绑定,而queue封装在looper中,通过mQueue=mLooper.mQueue;//即可获得消息队列
prepareMainLooper()这个方法调用prepare(这个方法中创建了一个looper对象),而prepareMainLooper()是为ui线程设置对应的looper,这样looper就与线程关联上了,同理消息队列也与线程关联。handler也与线程关联。
- 每一个handler都会关联一个消息队列,handler与looper绑定,而消息队列被封装在looper中,每一个looper又会关联一个线程,他们之间的关系是Handler(N):Looper(1):MeaasgeQueue(1):Thread(1)
- 对应looper:有两个重要的点:
Looper.prepare();//创建looper对象
looper获得后,通过Looper.loop()执行消息循环 - 过程叙述
- 实例化looper:如果handler在主线程创建,那么主线程会默认与其绑定一个looper和与之对应的消息队列,不用实例化looper;而如果handler在子线程创建,android系统默认情况下非主线程是没有开启looper的,所以需要我们手动初始化looper:Looper.prepare();
- 实例化Handler handler=new Handler();
- 执行消息循环:Looper.loop()。
- 实例化Message:有两种消息类型(message,runnable),通过handler的sendMessage(message)和post(runnable)发送消息。然后将消息压入到消息队列中。
-
Looper轮询消息,并调用handler.handleMeaasge()来让handler处理消息。
根据上图可以总结一个结论:
android中通过Handler机制来异步处理多线程之间的通信,就是多个线程之间共享一个MessageQueue