Looper分析

Looper分析

在 Handler 机制中,Looper 的作用是提供了一个消息循环 ( message loop ) 的机制,用于处理和分发消息。

Looper 是一个线程局部的对象,每个线程只能有一个 Looper 对象 。它通过一个无限循环来不断地从消息队列中取出消息,并将消息分发给对应的 Handler 进行处理。

在使用 Handler 机制时,我们可以通过调用 Looper.prepare() 方法来创建一个Looper对象,并通过 Looper.loop() 方法来启动消息循环。在消息循环开始后,Looper会不断地从消息队列中取出消息,然后将消息分发给对应的 Handler 进行处理。

Handler 可以通过调用 post()sendMessage() 等方法将消息发送到消息队列中,然后由 Looper 负责将这些消息取出并分发给对应的 Handler 进行处理。这样就实现了线程间的消息传递和处理。

Looper还可以通过调用 quit() 方法来终止消息循环,停止消息的处理。

下来以主线程内的 Looper 分析下。

Looper 创建/运行

App 运行,进程创建后主线程开始运行的入口在 ActivityThreadmain(String[] args) 方法。

java 复制代码
// ActivityThread.java  sdk30

public static void main(String[] args) {
	// ...... 一系列的初始化操作。
    // 创建主线程的 Looper 并设置到 ThreadLocal,同时创建了绑定的 MessageQueue。
    Looper.prepareMainLooper(); 

    // ......
    
    ActivityThread thread = new ActivityThread(); // 主线程对象创建
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) { // 主线程处理各事件的 Handler
        sMainThreadHandler = thread.getHandler();
    }

    // ......
    
    Looper.loop();  // Looper 开始无限循环,从 MessageQueue 中取消息,也同时保证了主线程的存活。

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

上面代码中 Looper 的创建与运行就两行。

  1. Looper.prepareMainLooper(); 方法的调用,创建了 **主线程 ** 的 Looper 对象,并将它设置到了 sThreadLocal 中。

    java 复制代码
    // Looper.java sdk30
    
    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));
    }
    
    @Deprecated
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    上面代码保证了一个线程只能有一个 Looper 对象:

    • if (sThreadLocal.get() != null) 判断表明 sThreadLocal 内对应于主线程的 Looper 对象只能存在一个。若主线程运行起来时发现已经有存在的 Looper 对象,将抛出异常,也就表明 app 进程直接crash。
    • prepareMainLooper() 被标注了 @DeprecatedLooperpublic 类,在 app 程序中是可以调用 Looper.prepareMainLooper() 方法的。换言之,在 sThreadLocal 中已经存在 Looper 对象的情况下,,可以再次调用方法 Looper.prepareMainLooper(),因此在 prepare(boolean quitAllowed) 一开始就先判断是否存在了 Looper 对象。进一步表明,一个线程中只能有一个 Looper
    • 赋值 sMainLooper

    这样主线程的 Looper 就创建完成了。

  2. Looper.loop(); 开启了 Looper 的无限循环,从 MessageQueue 中取消息,附带同时保证了主线程的存活。还负责将 msg 分发给对应的 Handler 执行。

相关推荐
lxysbly2 小时前
md模拟器安卓版带金手指2026
android
儿歌八万首2 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-19435 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
Jinkxs5 小时前
Gradle - 与Groovy/Kotlin DSL对比 构建脚本语言选择指南
android·开发语言·kotlin
&有梦想的咸鱼&5 小时前
Kotlin委托机制的底层实现深度解析(74)
android·开发语言·kotlin
LDORntKQH5 小时前
基于深度强化学习的混合动力汽车能量管理策略 1.利用DQN算法控制电池和发动机发电机组的功率分配 2
android
冬奇Lab5 小时前
Android 15 ServiceManager与Binder服务注册深度解析
android·源码·源码阅读
2501_916008897 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
独行soc9 小时前
2026年渗透测试面试题总结-20(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
常利兵9 小时前
2026年,Android开发已死?不,它正迎来黄金时代!
android