Android Framework学习七:Handler、Looper、Message
文章目录
- 简介
- Looper
- Message
- MessageQueue
- Handler
- Framework学习系列文章
简介
Looper当做一台传送装置,MessageQueue是传送带,传送带上放的是Message,Handler用于发送Message分发与接收处理。
Looper
frameworks/base/core/java/android/app/ActivityThread.java
ActivityThread.main是APP的入口函数,先调用Looper.prepareMainLooper创建Looper,再调用Looper.loop让它跑起来。
public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}Looper.loop();}
frameworks/base/core/java/android/os/Looper.java
public final class Looper {
...// sThreadLocal.get() will return null unless you've called prepare().@UnsupportedAppUsagestatic final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();@UnsupportedAppUsageprivate static Looper sMainLooper; // guarded by Looper.classprivate static Observer sObserver;@UnsupportedAppUsagefinal MessageQueue mQueue;final Thread mThread;...
}
ThreadLocal 是 Android 和 Java 中一个用于实现线程隔离的工具类,它能让每个使用该变量的线程都拥有独立的副本,线程间对该变量的操作互不影响。
APP入口函数会调用prepareMainLooper->prepare, 会新建一个Looper对象给
sThreadLocal,保证线程有且拥有一个只有自己能用的Looper对象。
sMainLooper通过myLooper函数赋值,其实就是sThreadLocal中的Looper对象
/*** Return the Looper object associated with the current thread. Returns* null if the calling thread is not associated with a Looper.*/public static @Nullable Looper myLooper() {return sThreadLocal.get();}
Looper.loop
loop()其实是在一个死循环中,不断执行loopOnce函数
/*** Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/@SuppressWarnings("AndroidFrameworkBinderIdentity")public static void loop() {final Looper me = myLooper();if (me == null) {throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}if (me.mInLoop) {Slog.w(TAG, "Loop again would have the queued messages be executed"+ " before this one completed.");}me.mInLoop = true;// 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();// Allow overriding a threshold with a system prop. e.g.// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'final int thresholdOverride =SystemProperties.getInt("persist.log.looper."+ Process.myUid() + "."+ Thread.currentThread().getName()+ ".slow", 0);me.mSlowDeliveryDetected = false;for (;;) {if (!loopOnce(me, ident, thresholdOverride)) {return;}}}
在loopOnce中会调用msg.target.dispatchMessage(msg)分发消息
private static boolean loopOnce(final Looper me,final long ident, final int thresholdOverride) {....Message msg = me.mQueue.next(); // might block....try {msg.target.dispatchMessage(msg);if (observer != null) {observer.messageDispatched(token, msg);}dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;} catch (Exception exception) {if (observer != null) {observer.dispatchingThrewException(token, msg, exception);}throw exception;} finally {ThreadLocalWorkSource.restore(origWorkSource);if (traceTag != 0) {Trace.traceEnd(traceTag);}}.... }
这个msg.target的target其实是Handler对象,msg.target.dispatchMessage调用的是Handler.dispatchMessage
Message
这个target就是Handler, 也就是Message中会有Handler的引用,
frameworks/base/core/java/android/os/Message.java
/*** Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>* members.* @param h The <em>target</em> value to set.* @param what The <em>what</em> value to set.* @param obj The <em>object</em> method to set.* @return A Message object from the global pool.*/public static Message obtain(Handler h, int what, Object obj) {Message m = obtain();m.target = h;m.what = what;m.obj = obj;return m;}
MessageQueue
MessageQueue是由链表组成的,用于存放Message
MessageQueue主要函数
Handler
发送Message时sendMessage最终都会调用enqueueMessage
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}/*** Enqueue a message into the message queue after all pending messages* before the absolute time (in milliseconds) <var>uptimeMillis</var>.* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>* Time spent in deep sleep will add an additional delay to execution.* You will receive it in {@link #handleMessage}, in the thread attached* to this handler.** @param uptimeMillis The absolute time at which the message should be* delivered, using the* {@link android.os.SystemClock#uptimeMillis} time-base.** @return Returns true if the message was successfully placed in to the* message queue. Returns false on failure, usually because the* looper processing the message queue is exiting. Note that a* result of true does not mean the message will be processed -- if* the looper is quit before the delivery time of the message* occurs then the message will be dropped.*/public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {MessageQueue queue = mQueue;if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}return enqueueMessage(queue, msg, uptimeMillis);}
会调用queue.enqueueMessage,这个queue其实是MessageQueue,把Message放入MessageQueue
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {msg.target = this;msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}
接收到消息后处理时
dispatchMessage会调用到handleMessage,就会进入Message的处理部分
frameworks/base/core/java/android/os/Handler.java
/*** Callback interface you can use when instantiating a Handler to avoid* having to implement your own subclass of Handler.*/public interface Callback {/*** @param msg A {@link android.os.Message Message} object* @return True if no further handling is desired*/boolean handleMessage(@NonNull Message msg);}/*** Subclasses must implement this to receive messages.*/public void handleMessage(@NonNull Message msg) {}/*** Handle system messages here.*/public void dispatchMessage(@NonNull Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}
Framework学习系列文章
Android Framework学习一:系统框架、启动过程
Android Framework学习二:Activity创建及View绘制流程
Android Framework学习三:zygote
Android Framework学习四:APP速度优化
Android Framework学习五:APP启动过程原理及速度优化
Android Framework学习六:Binder原理
Android Framework学习七:Handler、Looper、Message
作者:帅得不敢出门