Android消息机制

1.消息机制的简介
在Android中使用消息机制,我们首先想到的就是Handler。Handler是Android消息机制的上层接口。通过它可以轻松地将一个任务切换到Handler所在的线程中去执行。通常情况下,Handler的使用场景就是更新UI。

Handler的运行是需要底层的MessageQueue和Looper的支撑。在本消息机制中,主要有如下几个部分:
1、Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于不同的线程之间交换数据。可以使用what字段、arg1、arg2携带一些整型数据,使用obj字段携带一个Object对象。
2、Handler
Handler就是处理者的意思,它主要用于发送和处理消息,发送消息一般在主线程构造一个Handler,在其他线程调用Handler的sendMessage()方法,此时主线程的MessageQueue中会插入一条message,然后被Looper使用。Handler在创建时会通过ThreadLocal来获取当前线程的Looper来构造消息循环系统。
3、MessageQueue
MessageQueue是消息队列,每个线程中只会有一个MessageQueue对象,单链表维护,在插入和删除上有优势。主要用于存放所有通过Handler发送的消息,这部分消息会一直存在于消息队列中,等待被处理。在其next()中会无限循环,不断判断是否有消息,有就返回这条消息并移除。
4、Looper
 Looper创建时会创建一个MessageQueue,调用loop()方法时消息循环开始(死循环),会不断调用MessageQueue的next()方法,当有消息就传递到Handler的handlerMessage()方法中处理,否则阻塞在messageQueue的next()中。当Looper的quit()被调用的时候会调用messageQueue的quit(),此时next()会返回null,然后loop()方法也跟着退出。每个线程中也只会有一个Looper对象。

创建Handler后,重写hangleMessage()方法,然后通过Handler的post()方法将一个Runnable投递到Handler内部的Looper中去处理,也可以通过Handler的send()方法,发送一个message,该消息同样会在Looper中处理。send()方法的工作过程:当send()方法被调用时,它会调用MessageQueue的enqueueMessage()方法,该方法将这个消息放入到消息队列中(post()方法也是通过send()方法实现)。而Looper则会尝试在MessageQueue中取出待处理的消息,然后Runnable或者handler的handleMessage()方法就会被调用。由于Looper是运行在创建Handler所在的线程中的,这样Handler中的业务逻辑就被切换到创建Handler所在的线程中去执行了。
在这里插入图片描述

2.Android的消息机制分析
1.Looper
要想使用消息机制,首先要创建一个Looper。
初始化Looper
无参情况下,默认调用prepare(true);表示的是这个Looper可以退出,而对于false的情况则表示当前Looper不可以退出。不能重复创建Looper,只能创建一个。创建Looper,并保存在ThreadLocal。其中ThreadLocal是线程本地存储区(Thread Local Storage,简称为TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。
开启Looper

public static void loop() {
    final Looper me = myLooper();  //获取TLS存储的Looper对象 
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;  //获取Looper对象中的消息队列

    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) { //进入loop的主循环方法
        Message msg = queue.next(); //可能会阻塞,因为next()方法可能会无限循环
        if (msg == null) { //消息为空,则退出循环
            return;
        }

        Printer logging = me.mLogging;  //默认为null,可通过setMessageLogging()方法来指定输出,用于debug功能
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        msg.target.dispatchMessage(msg); //获取msg的目标Handler,然后用于分发Message 
        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
         
        }
        msg.recycleUnchecked(); 
    }
}

当next()取出下一条消息时,队列中已经没有消息时,next()会无限循环,产生阻塞。等待MessageQueue中加入消息,然后重新唤醒。
主线程中不需要自己创建Looper,这是由于在程序启动的时候,系统已经帮我们自动调用了Looper.prepare()方法。

2.Handler
创建Handler

public Handler() {
    this(null, false);
}

public Handler(Callback callback, boolean async) {
   .................................
    //必须先执行Looper.prepare(),才能获取Looper对象,否则为null.
    mLooper = Looper.myLooper();  //从当前线程的TLS中获取Looper对象
    if (mLooper == null) {
        throw new RuntimeException("");
    }
    mQueue = mLooper.mQueue; //消息队列,来自Looper对象
    mCallback = callback;  //回调方法
    mAsynchronous = async; //设置消息是否为异步处理方式
}

对于Handler的无参构造方法,默认采用当前线程TLS中的Looper对象,并且callback回调方法为null,且消息为同步处理方式。只要执行的Looper.prepare()方法,那么便可以获取有效的Looper对象。

3.发送消息
在子线程中通过Handler的post()方式或send()方式发送消息,最终都是调用了sendMessageAtTime()方法。

4.获取消息
当发送了消息后,在MessageQueue维护了消息队列,然后在Looper中通过loop()方法,不断地获取消息。其中最重要的是调用了queue.next()方法,通过该方法来提取下一条信息。

5.分发消息
在loop()方法中,获取到下一条消息后,执行msg.target.dispatchMessage(msg),来分发消息到目标Handler对象。

分发消息流程:
当Message的msg.callback不为空时,则回调方法msg.callback.run();
当Handler的mCallback不为空时,则回调方法mCallback.handleMessage(msg);
最后调用Handler自身的回调方法handleMessage(),该方法默认为空,Handler子类通过覆写该方法来完成具体的逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值