Looper.prepare()

本文详细介绍了Android中的Looper机制,包括如何为线程创建消息循环及消息处理流程。Looper用于封装线程中的消息循环,通过MessageQueue存放消息和事件,并确保一个线程只有一个Looper实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。

注:写在Looper.loop()之后的代码不会被立即执行,当调用后mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。


以下是Android API中的一个典型的Looper thread实现:

//Handler不带参数的默认构造函数:new Handler(),实际上是通过Looper.myLooper()来获取当前线程中的消息循环,
//而默认情况下,线程是没有消息循环的,所以要调用 Looper.prepare()来给线程创建消息循环,然后再通过,Looper.loop()来使消息循环起作用。


class LooperThread extends Thread
{
public Handler mHandler;
public void run()
{
Looper.prepare();
mHandler = new Handler()
{
public void handleMessage(Message msg)
{
// process incoming messages here
}
};
Looper.loop();
}


另,Activity的MainUI线程默认是有消息队列的。所以在Activity中新建Handler时,不需要先调用Looper.prepare()。

什么时候使用Looper.prepare()

当你的线程想拥有自己的MessageQueue的时候先Looper.prepare(),然后Looper.loop();
参照源码:
  1. public static final void prepare() {  
  2.        if (sThreadLocal.get() != null) {  
  3.            throw new RuntimeException("Only one Looper may be created per thread");  
  4.        }  
  5.        sThreadLocal.set(new Looper());  
  6.    }  
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }
这段代码就是通过ThreadLocal来产生一个Looper对象做为线程局部变量,然后调用Looper.loop()则是取出Looper对象中的MessageQueue进行消息循环了,这样形成了这个线程的消息队列。
一般情况下只会有主线程会调用prepare方法(ActivityThread的main函数)。
 

使线程拥有自己的消息列队,主线程拥有自己的消息列队,一般线程创建时没有自己的消息列队,消息处理时就在主线程中完成,如果线程中使用Looper.prepare()和Looper.loop()创建了消息队列就可以让消息处理在该线程中完成

<think>我们正在查找Looper.prepare()的具体代码实现。根据引用[1]和引用[2]的内容,我们可以得到以下信息:引用[1]中提供了Looper.prepare()方法的代码片段:```javapublicstaticvoidprepare(){prepare(true);}privatestaticvoidprepare(booleanquitAllowed){if(sThreadLocal.get()!=null){thrownewRuntimeException("OnlyoneLoopermaybecreatedperthread");}sThreadLocal.set(newLooper(quitAllowed));}```这里,prepare()方法调用了私有的prepare(boolean)方法,传入true表示允许退出。在prepare(boolean)方法中,首先检查当前线程是否已经存在Looper(通过sThreadLocal.get()判断),如果已经存在则抛出异常(因为一个线程只能有一个Looper)。然后,创建一个新的Looper对象(传入quitAllowed参数)并设置到sThreadLocal中。引用[2]补充说明:prepare()方法在一个工作线程中只能调用一次,调用后就可以通过Looper.myLooper()获取当前线程的Looper对象,也可以通过Looper.myQueue()获取消息队列。因此,Looper.prepare()的主要作用是为当前线程初始化一个Looper对象,并确保一个线程只有一个Looper。现在,我们按照要求生成相关问题。</think>### Looper.prepare() 源码实现分析 根据 Android 源码(以 Android 10 为例),`Looper.prepare()` 的核心实现如下: ```java // frameworks/base/core/java/android/os/Looper.java public final class Looper { private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>(); public static void prepare() { prepare(true); // 默认允许退出 } private static void prepare(boolean quitAllowed) { // 检查当前线程是否已存在Looper if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } // 创建新Looper并绑定到当前线程 sThreadLocal.set(new Looper(quitAllowed)); } // Looper构造函数 private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); // 创建消息队列 mThread = Thread.currentThread(); // 绑定当前线程 } } ``` #### 关键实现解析: 1. **线程唯一性保证** 通过 `sThreadLocal.get() != null` 检查确保每个线程只能创建一个 `Looper` 实例,否则抛出运行时异常[^1]。 2. **消息队列初始化** 在 `Looper` 构造函数中创建 `MessageQueue` 对象,核心参数 `quitAllowed` 控制是否允许退出循环[^1]。 3. **线程绑定机制** 使用 `ThreadLocal` 存储 `Looper` 实例,实现线程隔离: ```java public static @Nullable Looper myLooper() { return sThreadLocal.get(); } ``` 4. **主线程特殊处理** 系统主线程初始化时调用 `prepareMainLooper()`,其内部设置 `quitAllowed=false` 禁止退出: ```java public static void prepareMainLooper() { prepare(false); // 主线程不允许退出 sMainLooper = myLooper(); } ``` #### 典型使用场景: 工作线程中必须显式调用: ```java new Thread(() -> { Looper.prepare(); // 初始化Looper Handler handler = new Handler(); Looper.loop(); // 启动消息循环 }).start(); ``` 若不调用 `prepare()` 直接创建 `Handler`,将触发 `"Can't create handler inside thread that has not called Looper.prepare()"` 异常[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值