Android 异步消息处理机制

为什么谷歌要提出:“UI更新一定要在UI线程里实现”这一规则呢?原因如下:

为什么不能在子线程中更新UI - CSDN博客

目的在于提高移动端更新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),不起作用。

猜你喜欢

转载自blog.csdn.net/qq_35008279/article/details/82180758