2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Android-33源码分析: Handler消息机制

Android-33源码分析: Handler消息机制

时间:2019-12-15 10:11:37

相关推荐

Android-33源码分析: Handler消息机制

的声明:ActivityThread 管理应用进程中主线程的执行,根据AMS调度执行广播和其他操作Handler 发送消息并处理消息MessageQueue 用于存放消息的消息队列Looper 循环消息队列中的消息循环器Message 可在整个app中传递的消息

ActivityThreadpublic static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAndroidOs.install();// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);// Call per-process mainline module initialization.initializeMainlineModules();Process.setArgV0("<pre-initialized>");/*** 初始化Looper消息循环器,且初始化MessageQueue消息队列* prepare(false) false说明不可以移除消息队列中的所有消息* mQueue = new MessageQueue(quitAllowed);* mThread = Thread.currentThread()*/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 绑定一些类 比如:Instrumentation等等* ....* 通过AMS发送绑定Application的请求完成Application的创建* 注意:在创建Application之前会先去判断应用内是否存在ContentProvider的注册并启动它* 故:ContentProvider中的onCreate会比Application中的onCreate要先执行的原因*/ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}/*** 启动消息循环启 如果启动失败直接退出*/// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}

Looperpublic static void prepareMainLooper() {// 准备一个Looperprepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}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));}/*** 创建一个MessageQueue消息队列* @param quitAllowed*/private Looper(boolean quitAllowed) {mQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();}private static boolean loopOnce(final Looper me,final long ident, final int thresholdOverride) {// 通过消息队列中next指针获取消息 如果没有消息会调native方法去阻塞Message msg = me.mQueue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return false;}/*** 可以考虑做卡顿问题的分析* 可以Looper.getMainLooper().setMessageLogging(printer)打印出这个日志* * logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);* 存在字符串拼接,频繁调用会创建大量对象造成内存抖动* 后台线程频繁获取主线程堆栈对性能有一定影响,获取主线程堆栈会暂停主线程的运行*/// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " "+ msg.callback + ": " + msg.what);}// Make sure the observer won't change while processing a transaction.final Observer observer = sObserver;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;Object token = null;if (observer != null) {token = observer.messageDispatchStarting();}long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);try {// 获取消息中的Handler进行消息的分发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);}}if (logSlowDelivery) {if (me.mSlowDeliveryDetected) {if ((dispatchStart - msg.when) <= 10) {Slog.w(TAG, "Drained");me.mSlowDeliveryDetected = false;}} else {if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",msg)) {// Once we write a slow delivery log, suppress until the queue drains.me.mSlowDeliveryDetected = 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);}/*** 该消息使用完之后 清空该消息里面的数据*/msg.recycleUnchecked();return true;}

MessageQueueMessageQueue(boolean quitAllowed) {mQuitAllowed = quitAllowed;/*** 初始化Native方法,返回值NativeMessageQueue指针地址*/mPtr = nativeInit();}Message next() {// Return here if the message loop has already quit and been disposed.// This can happen if the application tries to restart a looper after quit// which is not supported.final long ptr = mPtr;if (ptr == 0) {return null;}int pendingIdleHandlerCount = -1; // -1 only during first iterationint nextPollTimeoutMillis = 0;for (;;) {if (nextPollTimeoutMillis != 0) {Binder.flushPendingCommands();}/***** 阻塞操作,nextPollTimeoutMillisddd等待时长* nativePollOnce用于“等待”, 直到有下一条消息可用为止* nextPollTimeoutMillis 为-1则阻塞*/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) {// Stalled by a barrier. Find the next asynchronous message in the queue.do {prevMsg = msg;msg = msg.next;} while (msg != null && !msg.isAsynchronous());}if (msg != null) {// 从消息队列中拿到的Message的执行时间,比当前时间还后面,则计算其差值,用于后面休眠。if (now < msg.when) {// Next message is not ready. Set a timeout to wake up when it is ready.nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);} else {// 如果从消息队列中获取的Message小于当前时间,则返回给Looper进行派发和处理// Got a message.mBlocked = false;if (prevMsg != null) {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();}if (pendingIdleHandlerCount <= 0) {// No idle handlers to run. Loop and wait some more.mBlocked = true;continue;}if (mPendingIdleHandlers == null) {mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];}mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);}/*** 如果没有消息处理* 判断是否存在闲时处理器调用queueIdle方法*/// 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 handlerboolean keep = false;try {// 如果返回false则只处理一次 并且移除这个闲时处理器keep = idler.queueIdle();} catch (Throwable t) {Log.wtf(TAG, "IdleHandler threw exception", t);}if (!keep) {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.nextPollTimeoutMillis = 0;}}boolean enqueueMessage(Message msg, long when) {if (msg.target == null) {throw new IllegalArgumentException("Message must have a target.");}synchronized (this) {if (msg.isInUse()) {throw new IllegalStateException(msg + " This message is already in use.");}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) {// 如果p为空,表明消息队列中没有消息,那么msg将是第一个消息,needwake需要根据mBlocked复值// New head, wake up the event queue if blocked.msg.next = p;mMessages = msg;needWake = mBlocked;} else {// 如果p不为空,表明消息队列中还有剩余的消息,需要将新的msg添加到对应的位置。// 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.needWake = mBlocked && p.target == null && msg.isAsynchronous();Message prev;for (;;) {prev = p;p = p.next;// 从消息队列中取出消息,判断该消息的触发时间,与要新添加的Message的时间对比。// 如果新添加的Message时间小于 当前消息队列中获取的Message的时间,则直接break。if (p == null || when < p.when) {break;}if (needWake && p.isAsynchronous()) {needWake = false;}}// 将新添加的Message添加到该队列的指定位置msg.next = p; // invariant: p == prev.nextprev.next = msg;}// 判断是否需要唤醒// We can assume mPtr != 0 because mQuitting is false.if (needWake) {// 调用nativeWake,触发nativePollOnce函数结束等待。nativeWake(mPtr);}}return true;}

Handlerpublic Handler() {this(null, false);}/*** 外部传递一个looper* @param looper*/public Handler(@NonNull Looper looper) {this(looper, null, false);}public Handler(@Nullable Callback callback) {this(callback, false);}public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {mLooper = looper;// Handler中会持有消息循环器mQueue = looper.mQueue;// Handler中会持有消息队列mCallback = callback;mAsynchronous = async;}public final boolean post(@NonNull Runnable r) {return sendMessageDelayed(getPostMessage(r), 0);}public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {return sendMessageAtTime(getPostMessage(r), uptimeMillis);}public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);}public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {return sendMessageDelayed(getPostMessage(r), delayMillis);}public final boolean postDelayed(Runnable r, int what, long delayMillis) {return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);}private static Message getPostMessage(Runnable r) {Message m = Message.obtain();m.callback = r;return m;}public final boolean sendMessage(@NonNull Message msg) {return sendMessageDelayed(msg, 0);}public final boolean sendEmptyMessage(int what){return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageDelayed(msg, delayMillis);}public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {MessageQueue queue = mQueue; // 如果消息队列为null直接退出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);}private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {msg.target = this;// 把当前Handler对象复值msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}

HandlerHandler(Looper looper):有传递消息循环器,那就直接使用该looperHandler(Callback callback, boolean async):没有如looper就去Looper.myLooper()获取一个Looper mLooper=Looper.myLooper()MessageQueue mQueue= mLooper.mQueuepost(Runnable r):会自动生成一个msg然后发送出去postAtTime(Runnable r, long uptimeMillis):会自动生成一个msg然后延迟x发送出去sendMessageDelayed(getPostMessage(r), 0):得到msg发送消息sendMessage(Message msg):发送一个指定msgsendMessageDelayed(Message msg, long delayMillis)延迟发送一个指定msgsendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis):方法中会得到mQueue 即消息队列MessageQueueenqueueMessage(queue, msg, uptimeMillis):该方法msg.target=this;意味着msg中持有一个handler;通过queue.enqueueMessage(msg, uptimeMillis)把msg消息以链表的结构存储(先进先出原则)Looper Looper(boolean quitAllowed)唯一的构造方法,quitAllowed是否支持停止消息循环mQueue = new MessageQueue(quitAllowed);构造方法中构造消息队列对象mThread = Thread.currentThread();loop():开启消息循环唯一入口Looper me = myLooper()判断当前Looper是否存在不存在抛出异常for()开启循环Message msg = me.mQueue.next():获取消息队列中的消息msg.target.dispatchMessage(msg)把消息分发下去msg.callback != null->handleCallback(msg):callback实现Runnable其run()做处理工作;mCallback != null->mCallback.handleMessage(msg): mCallback实现Callback由其handleMessage进行处理;handleMessage(msg):通过重写Handler中handleMessage(msg)处理消息.MessageQueueMessage next():开启消息读取nativePollOnce(ptr, nextPollTimeoutMillis):表示下一次轮询超时时间,nextPollTimeoutMillis=-1没有消息需阻塞,0开启新一轮或已经执行完idle闲时事件处理keep = idler.queueIdle():如没消息执行该方法,返回false移除这个接口,否则不移除boolean enqueueMessage(Message msg, long when)msg.target == null 如果Handler为null直接抛出异常needWake为true说明有消息加入需要处理nativeWake(mPtr)通知其next()中需要处理数据注意:可以使用闲暇handler做一些不是很急需的事情Looper.myQueue().addIdleHandler(IdleHandler接口 handler)IdleHandler接口实现queueIdle()返回值:false该queueIdle只执行一次,true该queueIdle可在空闲时直执行针对app主线程崩溃问题 我们可以对dispatchMessage方法进行异常捕获,但是该方法是由Looper.loop中的消息触发,所以无法捕获该异常。但是我们可以对Looper的loop方法进行一个异常捕获,保证所有主线程的异常全部被捕获到。为什么可以这么说?因为Looper.loop是开启所有主线程消息循环,在ActivityThread.main中被开启执行。故我们可以发送一个消息去执行自己开启的loop方法比如:Log.e(TAG, "通过handler发送数据执行run 如果不通过发送消息方式可能会阻塞后面运行的程序");new Handler(Looper.getMainLooper()).post(() -> {Log.e(TAG, "死循环为保证每次捕获崩溃之后能再次开启消息循环");while (true) {try {Log.e(TAG, "保证崩溃之后被try住异常 同时记录主线程崩溃次数和崩溃信息");Looper.loop();} catch (Throwable e) {mainCount++;Log.e(TAG, "当前主线程崩溃次数==" + mainCount + "==崩溃信息:" + e.getMessage());}}});

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。