欢迎访问我的个人博客,一起学习交流。^_^
为什么谷歌要提出:“UI更新一定要在UI线程里实现”这一规则呢?原因如下:
目的在于提高移动端更新UI的效率和和安全性,以此带来流畅的体验。原因是:
Android的UI访问是没有加锁的,多个线程可以同时访问更新操作同一个UI控件。也就是说访问UI的时候,android系统当中的控件都不是线程安全的,这将导致在多线程模式下,当多个线程共同访问更新操作同一个UI控件时容易发生不可控的错误,而这是致命的。所以Android中规定只能在UI线程中访问UI,这相当于从另一个角度给Android的UI访问加上锁,一个伪锁。
Android 中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。
先让我们一句话总结,再开始分析。
Looper不断获取MessageQueue中的一个Message,然后交给Hanlder处理。
private Handler handler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case UPDATE_TEXT:
//UI操作
breakl
default:
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);//将Message对象发送出去
}
}).start();
1. Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。
2. Handler
Handler是处理者,它主要是用于发送和处理消息的、发送消息一般是使用Handler的sendMessahe() 方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler的handleMessage() 方法中。在一个线程中只能有一个Looper和MessageQueue,但是可以有多个Handler,而且这些Handler可以共享一个Looper和MessageQueue。
3. MessageQueue
MessageQueue是消息队列的意思,它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。
4. Looper
Looper是每个线程中的MessageQueue的管家,调用Looper的loop() 方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue 中存在一条消息,就回将它取出,并传递到Handler 的 handleMessage() 方法中。每个线程中也只会有一个Looper对象。
5. 异步消息处理的整个流程
当应用程序开启时,系统会自动为UI线程创建一个MessageQueue(消息队列)和Looper循环处理对象。首先需要在主线程中创建一个Handler对象,并重写handlerMessage()方法。然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。之后这条消息就会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,并找到与消息对象对应的Handler对象,然后调用Handler的handleMessage()方法。由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行UI操作了。
6. 源码分析
深入理解Message, MessageQueue, Handler和Looper
Android 异步消息处理机制前篇(二):深入理解Message消息池
Android多线程—-异步消息处理机制之Handler详解
从应用角度看Android源码 - 是谁调用的ActivityThread的main方法
7. Handler.removeMessages的作用
1、这个方法使用的前提是之前调用过sendEmptyMessageDelayed(0, time),意思是延迟time执行handler中msg.what=0的方法;
2、在延迟时间未到的前提下,执行removeMessages(0),则上面的handler中msg.what=0的方法取消执行;
3、在延迟时间已到,handler中msg.what=0的方法已执行,再执行removeMessages(0),不起作用。