Android Java层 Looper 机制

本文详细介绍了Android Java层的Looper、MessageQueue、Handler机制,包括主线程和子线程消息队列的创建、Looper.loop()进入消息循环的过程、MessageQueue的next()函数的工作原理,以及如何通过Handler发送和处理消息。文章强调了同步消息和异步消息的区别,并解释了IdleHandler在空闲时执行任务的功能。
摘要由CSDN通过智能技术生成

写在前面

本节主讲Android消息循环机制中java 部分:Jave层的Looper,MessageQueue,Handler,涉及到native部分会先做简单解释跳过。后续会在第三节将jave与native 层串联起来。

涉及到的相关java的文件路径:

  • Looper.java (android-5.1.0_r3\frameworks\base\core\java\android\os)
  • MessageQueue.java (android-5.1.0_r3\frameworks\base\core\java\android\os)
  • Message.java (android-5.1.0_r3\frameworks\base\core\java\android\os)
  • Handler.java (android-5.1.0_r3\frameworks\base\core\java\android\os)

基本概念

  • Looper :负责创建消息队列,并执行消息循环。
  • MessageQueue :消息队列,消息以链表形式组织。Message不是直接加入到MessageQueue,而是通过一个与该looper绑定的handler添加进来的。
  • Message :消息的格式。
  • Handler:派发消息以及处理消息。

创建线程消息队列

主线程消息队列是在应用程序启动时,由framework层帮忙创建的,开发者无需关心。

而如果开发者希望自己创建的子线程也拥有消息循环机制,则需开发者自己去创建。

主线程消息队列的创建

消息队列是与Looper一对一绑定的,在Looper的构造函数中会创建MessageQueue。所以从Looper的构造函数开始。

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

Looper的构造函数是private的,因为每个线程中只能有一个looper,所以采用ThreadLocal来保存looper 对象。

// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;  // guarded by Looper.class

我们知道,系统启动应用程序的时候,就帮我们把主线程中的Looper创建好了,那是哪里创建的呢?

Android 创建应用程序的入口函数是ActivitThread.java 的main() 函数,在main() 函数中调用了Looper的静态方法prepareMainLooper(),将创建了Looper对象以及消息队列。

public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    ...
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
Looper . prepareMainLooper()

Looper.prepareMainLooper()函数中,会先透过prepare() 创建looper,如果发现之前已经创建过,存在重复创建的话,则会抛出异常,也就是一个线程中只能有一个looper对象的存在。所以Looper中会以ThreadLocal 来保存该对象。即为该变量在每个线程中提供独立的副本。

public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

prepare() 函数中,new 了一个Looper 对象,并将其保存为线程本地变量。

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

至此,主线程的Looper对象就创建好了,它是一个ThreadLocal变量, MessageQueue也创建好了。

子线程消息队列的创建

子线程如果需要消息循环机制的话,则需要开发者主动调用Looper.prepare()创建消息队列。

Looper.prepare()
 /** Initialize the current thread as a looper.
  * This gives you a chance to create handlers that then reference
  * this looper, before actually starting the loop. Be sure to call
  * {@l
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值