0. 系列文章汇总
- Android Handler消息机制01-Message源码学习
- Android Handler消息机制02-Looper源码学习
- Android Handler消息机制03-Message源码学习
1.源码
本文主要是对Looper类的源码进行解析学习,用于更深入的理解Handler消息机制
Looper的源码路径为:android.os.Looper
1.2 典型案例
如下展示了一个源码中提供的典型实例
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();
}
}
如上所示的是在一个子线程构建一个Handler,但是在实际开发中不建议这么做。一般来说Handler机制是用于子线程往主线程传递消息用于UI更新操作。如果实在要在子线程创建,请使用HandlerThread进行创建
/**
* Looper类被用于运行一个线程的消息循环,消息默认没有与之关联的消息循环,为了创建一个,在运行循环的线程中调用Looper.prepare,
* 然后调用loop来处理消息直到循环停止。
*
* <p>与消息循环交互的大多数交互是通过Handler类。
*/
public final class Looper {
/*
* API Implementation Note:
*
* 该类基于MessageQueue去设置和管理事件循环,影响队列状态的API应在MessageQueue或者Handler上定义,而不是在Looper本身上定义,
* 例如默认Handlers和同步屏障在队列中定义,而prepare、loop和quit定义在Looper中
*/
private static final String TAG = "Looper";
// sThreadLocal 会返回null 直到你调用prepare,表示当前线程的Looper对象
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
@UnsupportedAppUsage
private static Looper sMainLooper; // 静态关联主线程的Looper
private static Observer sObserver;
@UnsupportedAppUsage
final MessageQueue mQueue;
final Thread mThread;
//
private boolean mInLoop;
@UnsupportedAppUsage
private Printer mLogging;
private long mTraceTag;
/**
* If set, the looper will show a warning log if a message dispatch takes longer than this.
* 如果赋值,Looper会打印一个告警日志如果消息处理耗时比这个值大。
*/
private long mSlowDispatchThresholdMs;
/**
* If set, the looper will show a warning log if a message delivery (actual delivery time -
* post time) takes longer than this.
* 如果被赋值,且消息分发(实际 delivery time -post time)耗时过长且会打印一个告警日志
*/
private long mSlowDeliveryThresholdMs;
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread(); //mThread置为当前线程
}
/**
* 初始化当前线程为一个Looper
* 这提供了在实际开始loop之前,创建关联当前Looperr的Handler的时机,
* 确保在调用此方法后再调用#loop(),然后通过#quit()来结束他
*
*/
public static void prepare() {
prepare(true);
}
/**
* 准备此Looper
* @param quitAllowed 是否允许此Hnadler停止
*/
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));
}