Handler源码
Posted cao_null
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Handler源码相关的知识,希望对你有一定的参考价值。
Handler
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//调用了Looper
mLooper = Looper.myLooper();
if (mLooper == null) {//为空则抛异常
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//获取MessageQueue
mQueue = mLooper.mQueue;
mCallback = callback;
//异步先按住不表
mAsynchronous = async;
}
Looper
Looper如此关键,没有就crash,看下Looper生成的过程
public static @Nullable Looper myLooper() {
return sThreadLocal.get();//ThreadLocal保证每个线程都有独立的Looper
}
//创建过程默认能退出
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");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
//创建MessageQueue
mQueue = new MessageQueue(quitAllowed);
//获取当前线程
mThread = Thread.currentThread();
}
单独分析主线程也就是UI线程创建Looper过程
//主线程创建sMainLooper
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
//ActivityThread
public static void main(String[] args) {
...
//创建主线程Looper
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//启动looper
Looper.loop();
//无限循环走到这说明出异常了
throw new RuntimeException("Main thread loop unexpectedly exited");
}
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
//官方注释要求确保要调用
public static void loop() {
final Looper me = myLooper();
if (me == null) {//必须先prepare
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();
// 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("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
//死循环
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
//没消息说明正在推出
return;
}
// This must be in a local variable, in case a UI event sets the logger
//打印日志调试用
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
if (thresholdOverride > 0) {
slowDispatchThresholdMs = thresholdOverride;
slowDeliveryThresholdMs = thresholdOverride;
}
final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
final boolean needStartTime = logSlowDelivery || logSlowDispatch;
final boolean needEndTime = logSlowDispatch;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
try {
//分发
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {//trace相关
Trace.traceEnd(traceTag);
}
}
if (logSlowDelivery) {
if (slowDeliveryDetected) {
if ((dispatchStart - msg.when) <= 10) {
Slog.w(TAG, "Drained");
slowDeliveryDetected = false;
}
} else {
if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
msg)) {
// Once we write a slow delivery log, suppress until the queue drains.
slowDeliveryDetected = true;
}
}
}
if (logSlowDispatch) {
showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
//回收message
msg.recycleUnchecked();
}
}
MessageQueue和Message
public final class Message implements Parcelable {//继承自Parcelable
public int what;
public Object obj;
//下面的是访问权限是包内
/*package*/ int flags;
/*package*/ long when;
/*package*/ Bundle data;
/*package*/ Handler target;
/*package*/ Runnable callback;
// sometimes we store linked lists of these things
/*package*/ Message next;
/** @hide */
//下面是static修饰的
public static final Object sPoolSync = new Object();//同步锁
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;//数据池最大size
public Message() {
}
//生成Message的时候最终都是调用obtain
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;//返回当前sPool,然后挪动next指针
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();//如果超过了就重新new
}
//这是回收
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {//小于最大容量
next = sPool;//挪动指针
sPool = this;
sPoolSize++;
}
}
}
}
这里我们知道了message的数据结构是通过next串联起来的,并且最好使用obtain而避免自己new,可以提高性能。
然后是MessageQueue
public final class MessageQueue {
//能否退出
private final boolean mQuitAllowed;
@SuppressWarnings("unused")
private long mPtr; //native用的
Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
private IdleHandler[] mPendingIdleHandlers;
private boolean mQuitting;
// Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
private boolean mBlocked;
// The next barrier token.
// Barriers are indicated by messages with a null target whose arg1 field carries the token.
private int mNextBarrierToken;
//下面这些都是native方法,暂时不深究
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
//主线程不允许退出,子线程允许
mQuitAllowed = quitAllowed;
//记录消息队列
mPtr = nativeInit();
}
next方法信息量比较大
Message next() {
final long ptr = mPtr;
if (ptr == 0) {// message的loop已经退出而且执行了disposed.
return null;
}
int pendingIdleHandlerCount = -1; // 只有第一次是-1
int nextPollTimeoutMillis = 0;
for (;;) {//又是一个死循环
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//阻塞方法,会被wake唤醒,也可以在nextPollTimeoutMillis时间后唤醒
//nextPollTimeoutMillis是0立即返回,-1就阻塞,否则等到nextPollTimeoutMillis时间后返回
nativePollOnce(ptr, nextPollTimeoutMillis);
//加锁
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
//这里target是null,说明遇到了barrier
do {
prevMsg = msg;//如果执行了这里
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());//找到下一个异步消息为止
}
if (msg != null) {
if (now < msg.when) {
// 下个消息时间还没到,设置等待时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {//看上面执行了prevMsg赋值,说明找到了异步消息,则重新链接message表
prevMsg.next = msg.next;
} else {//否则直接挪动到下一个
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();//设置一个使用中标志位,安全回收的时候用
return msg;
}
} else {
// No more messages.没信息重置为1
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0//循环第一次能走到这
&& (mMessages == null || now < mMessages.when)) {//当前没有消息
pendingIdleHandlerCount = mIdleHandlers.size();
}
//如果依然是-1说明不能执行IdleHandler,所以block,跳出循环,如果nextPollTimeoutMillis也是-1则回到之前的nativepullonce
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
//初始化最少4个handlers
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();//执行具体的queueIdle
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {//如果返回true则remove,否则无限循环
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
//重置,所以之后就不会再执行了
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
//有可能有普通消息过来,直接设置0,不等待进入下次循环
nextPollTimeoutMillis = 0;
}
}
看完了next出列,接下来看enqueueMessage入列。
boolean enqueueMessage(Message msg, long when) {
//两个必要的检查,为什么必须有target?刚才next还有没有target的情况,晚点再返回来看
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {//如果正在退出就崩溃
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
//一些赋值操作
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {//之前没有消息或者已经到了触发时间
//新入列的插入头部
msg.next = p;
mMessages = msg;
needWake = mBlocked;//之前无限等待现在就需要唤醒
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
//是否唤醒需要看target异步消息
needWake = mBlocked && p.target == null && msg.isAsynchronous();//有同步屏障而且这个消息是一个异步消息则假定需要唤醒
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {//循环到了结尾或者到了合适时间
break;
}
if (needWake && p.isAsynchronous()) {//如果循环发现在这之前还有其他异步消息不唤醒,综上就是只有当前存在同步屏障,且这个消息是第一个异步消息才唤醒
needWake = false;
}
}
//插入队列中间
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);//唤醒
}
}
return true;
}
接下来看一下同步屏障是什么
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());//同步屏障是隐藏方法,且只支持当前时间
}
private int postSyncBarrier(long when) {//这里的message没有target
// Enqueue a new sync barrier token.
// We don't need to wake the queue because the purpose of a barrier is to stall it.
synchronized (this) {
final int token = mNextBarrierToken++;
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
msg.arg1 = token;
Message prev = null;
Message p = mMessages;
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
if (prev != null) { // invariant: p == prev.next//插入合适的位置
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
然后是移除同步屏障
public void removeSyncBarrier(int token) {
// Remove a sync barrier token from the queue.
// If the queue is no longer stalled by a barrier then wake it.
synchronized (this) {
Message prev = null;
Message p = mMessages;
while (p != null && (p.target != null || p.arg1 != token)) {
prev = p;
p = p.next;
}
if (p == null) {//没找到就崩溃
throw new IllegalStateException("The specified message queue synchronization "
+ " barrier token has not been posted or has already been removed.");
}
final boolean needWake;
if (prev != null) {
prev.next = p.next;
needWake = false;//之前还有其他消息不唤醒
} else {
mMessages = p.next;
needWake = mMessages == null || mMessages.target != null;//看当前消息再决定是否唤醒
}
p.recycleUnchecked();//回收
// If the loop is quitting then it is already awake.
// We can assume mPtr != 0 when mQuitting is false.
if (needWake && !mQuitting) {
nativeWake(mPtr);
}
}
}
小结:
next的时候,假设有同步屏障,接下来只取异步消息,同步消息全部等待,来保证异步消息尽快执行。查看调用,使用同步屏障的地方主要在编舞者等系统关键时刻。消息的入队和出队在这基本分析完了,接下来是事件分发。
消息分发
Looper中调用了msg.target.dispatchMessage,具体看下
public void dispatchMessage(Message msg) {
if (msg.callback != null) {//先判断msg是否有callback,有就执行handleCallback
handleCallback(msg);
} else {
if (mCallback != null) {//否则调用handler的callback
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//没人处理走这
}
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
还有时间发送的post
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
//最终都执行这个,传入两个必备的参数,Message和时间
public boolean sendMessageAtTime(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);
}
总结
分工
Message:消息本身,存储一些target,data之类的数据
MessageQueue:消息队列主要维护消息,取出next或者插入数据enqueueMessage,也维护同步屏障异步消息等逻辑。
Looper:维持线程和Looper循环对应关系,分发到对应的msg。
Handler:负责发送和处理最终事件逻辑。
系统UI相关
同步屏障:加入同步屏障后,同步消息全部阻塞,异步消息能正常执行。
异步消息:可以理解为紧急消息,避免因为同步消息过多导致执行不及时。
使用在编舞者等系统UI关键操作中,避免消息过多导致系统关键操作卡顿。
本地方法
nativePollOnce:维持主线程不退出,并且阻塞逻辑,不占用CPU资源
nativeWake:适当时机唤醒循环
更多native方法逻辑,后续整理再发
以上是关于Handler源码的主要内容,如果未能解决你的问题,请参考以下文章