Looper类的重要字段
字段汇总
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; final Thread mThread;</span>
ThreadLocal 静态引用 :存储当前线程的Looper对象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
Looper引用 :静态持有主线程的Looper对象
private static Looper sMainLooper; // guarded by Looper.class
MessageQueue 引用 :当前Looper对象的消息队列
final MessageQueue mQueue;
- final修饰,表示当前Looper最多只能有一个消息对象对象
Thread引用 :记录创建当前Looper对象所在的线程
final Thread mThread;
Looper类的重要方法
私有的构造器
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
- 创建了 MessageQueue
- 记录创建当前Looper对象所在的线程引用
- 构造器私有,需要调用其他方法创建Looper对象
如何创建Looper
子线程
public static void prepare() { prepare(true); } 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)); }
- 静态方法prepare进行创建Looper对象
- 创建Looper对象之后,存储在线程私有数据ThreadLocal中
- 对于已经创建过Looper对象的线程,再进行prepare,会引起崩溃。从代码层面,一个线程只能有一个Looper对象。崩溃信息为 "Only one Looper may be created per thread"
主线程 : 主线程的创建不同于子线程
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
- main looper由android系统创建
- app 开发者永远不需要自己去调用此方法,调用此方法会抛出异常。崩溃信息为 "The main Looper has already been prepared."
启动loop循环
public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } final long traceTag = me.mTraceTag; if (traceTag != 0) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } 。。。省略代码 msg.recycleUnchecked(); } }
- loop为静态方法
- 调用loop之前没有调用prepare,会抛出异常,提示 “No Looper; Looper.prepare() wasn't called on this thread.”
- loop方法的核心是一个for的死循环
- loop循环主要做了三件事:
- 从消息队列中取出消息
- dispatch message
- recycle message
- loop的终止条件是消息队列没有了消息
Quits Looper
quit
/** * Quits the looper. * <p> * Causes the {@link #loop} method to terminate without processing any * more messages in the message queue. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p><p class="note"> * Using this method may be unsafe because some messages may not be delivered * before the looper terminates. Consider using {@link #quitSafely} instead to ensure * that all pending work is completed in an orderly manner. * </p> * * @see #quitSafely */ public void quit() { mQueue.quit(false); }
- 调用此方法后,不再处理post message 请求,如 sendMessage 会返回false
- 调用此方法,已经等待的消息执行将终止
- 如果想保证等待状态的消息处理完成,需要使用quitSafely
quitSafely
/** * Quits the looper safely. * <p> * Causes the {@link #loop} method to terminate as soon as all remaining messages * in the message queue that are already due to be delivered have been handled. * However pending delayed messages with due times in the future will not be * delivered before the loop terminates. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p> */ public void quitSafely() { mQueue.quit(true); }
- 当剩余的消息处理完毕之后,立即停止looper
- 消息处理完之前,loop不会停止
一些其他方法
获取创建此looper的线程引用
/** * Gets the Thread associated with this Looper. * * @return The looper's thread. */ public @NonNull Thread getThread() { return mThread; }
获取此looper的消息队列
/** * Gets this looper's message queue. * * @return The looper's message queue. */ public @NonNull MessageQueue getQueue() { return mQueue; }
获取主线程looper对象
/** * Returns the application's main looper, which lives in the main thread of the application. */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } }