
handler是什么handler是Android提供用来更新UI的一套消息机制也是一套消息处理的机制发送和处理消息handler原理handler负责消息发送looper负责接收handler发送过来的消息并把消息发送给handlermessageQueue存储消息的容器这里先说明一下ThreadLocal主要在线程中保存变量信息主要有两个比较重要的方法一个是get方法一个是set方法publicvoidset(Tvalue){Thread currentThreadThread.currentThread();Values valuesvalues(currentThread);if(valuesnull){valuesinitializeValues(currentThread);}values.put(this,value);}image.gifset方法设置当前线程的值使用键值对的形式存储Thread和looper之间的关系Thread作为keylooper作为valuepublicTget(){// Optimized for the fast path.Thread currentThreadThread.currentThread();Values valuesvalues(currentThread);if(values!null){Object[]tablevalues.table;int indexhashvalues.mask;if(this.referencetable[index]){return(T)table[index1];}}else{valuesinitializeValues(currentThread);}return(T)values.getAfterMiss(this);}image.gifget方法就是取出当前线程对应的looper也就是说ThreadLocal是负责thread和looper之间的关系的下面看一下Looper.prepare()方法privatestaticvoidprepare(boolean quitAllowed){if(sThreadLocal.get()!null){thrownewRuntimeException(Only one Looper may be created per thread);}sThreadLocal.set(newLooper(quitAllowed));}默认情况下ThreadLocal是没有存储的所以要创建一个新的looperprivateLooper(boolean quitAllowed){mQueuenewMessageQueue(quitAllowed);mThreadThread.currentThread();}image.gif默认情况下ThreadLocal是没有存储的所以要创建一个新的looperprivateLooper(boolean quitAllowed){mQueuenewMessageQueue(quitAllowed);mThreadThread.currentThread();}image.gif从looper方法中创建了一个MessageQueue在looper中维护着一个消息队列知道了looper和MessageQueue之后究竟handler跟这两者有什么关系呢继续看源码publicHandler(Callback callback,booleanasync){if(FIND_POTENTIAL_LEAKS){final Class?extendsHandlerklassgetClass();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());}}mLooperLooper.myLooper();if(mLoopernull){thrownewRuntimeException(Cant create handler inside thread that has not called Looper.prepare());}mQueuemLooper.mQueue;mCallbackcallback;mAsynchronousasync;}image.gif首先调用Looper.myLooper()publicstaticNullable LoopermyLooper(){returnsThreadLocal.get();}image.gif获得当前的looper对象通过looper拿到MessageQueue就完成了handler和looper之间的关联下面继续看handler的消息发送publicbooleansendMessageAtTime(Message msg,long uptimeMillis){MessageQueue queuemQueue;if(queuenull){RuntimeException enewRuntimeException(this sendMessageAtTime() called with no mQueue);Log.w(Looper,e.getMessage(),e);returnfalse;}returnenqueueMessage(queue,msg,uptimeMillis);}image.gif先获得当前的消息队列如果队列为空就抛出异常不为空向消息队列中插入消息privatebooleanenqueueMessage(MessageQueue queue,Message msg,long uptimeMillis){msg.targetthis;if(mAsynchronous){msg.setAsynchronous(true);}returnqueue.enqueueMessage(msg,uptimeMillis);}image.gif插入消息之前就指定消息发送给谁msg.target默认情况下发送给自己的handler然后把消息放入队列中handler就完成了发送message到MessageQueue的过程那么消息又是如何轮询的呢publicstaticvoidloop(){final Looper memyLooper();if(menull){thrownewRuntimeException(No Looper; Looper.prepare() wasnt called on this thread.);}final MessageQueue queueme.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 identBinder.clearCallingIdentity();for(;;){Message msgqueue.next();// might blockif(msgnull){// No message indicates that the message queue is quitting.return;}// This must be in a local variable, in case a UI event sets the loggerPrinter loggingme.mLogging;if(logging!null){logging.println( Dispatching to msg.target msg.callback: msg.what);}msg.target.dispatchMessage(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 wasnt corrupted.final long newIdentBinder.clearCallingIdentity();if(ident!newIdent){Log.wtf(TAG,Thread identity changed from 0xLong.toHexString(ident) to 0xLong.toHexString(newIdent) while dispatching to msg.target.getClass().getName() msg.callback whatmsg.what);}msg.recycleUnchecked();}}image.gif通过myLooper()方法获取当前looper进而获得当前的消息队列然后通过MessageQueue的next方法获取消息消息为空时返回不为空时调用handler的dispatchMessage(msg)方法然后这个过程一直循环publicvoiddispatchMessage(Message msg){if(msg.callback!null){handleCallback(msg);}else{if(mCallback!null){if(mCallback.handleMessage(msg)){return;}}handleMessage(msg);}}image.gif首先查看msg.callback是否为空不为空时去调用handleCallback(msg)这个方法在handler的构造方法中存在可以实现消息的拦截为空只就调用handleMessage(msg)这个方法都是大家熟悉的不在描述整体的handler的原理就描述到这。总结handler在Android中扮演的非常重要的角色熟悉handler的原理不仅在面试的时候有用就连activity的生命周期也是通过handler发送消息详细请看Framewrok源码。很多人都没有Framewrok源码这方面的资料这里我整理了一份《Android Framework源码开发揭秘》分享给大家由于文档内容过多因此为了避免影响到大家的阅读体验在此只以截图展示部分内容详细完整版的看文末有免费的获取方式文末还有使用ChatGPT机器人小福利哦大家不要错过《Android Framework源码开发揭秘》本学习手册深入剖析了Android系统源代码详细讲解了Android框架初始化过程及主要组件的工作原理,旨在通过实例和案例介绍 Android Framework 的核心概念和技术从而帮助开发者更好地理解 Android 应用程序的设计和开发。该手册适合具有一定 Android 应用开发经验的程序员希望能通过深入学习 Android Framework 来帮助开发者更好地理解和掌握这一技术。第一章 系统启动流程分析Android系统完整的启动过程从系统层次角度可分为 Linux 系统层、Android 系统服务层、Zygote进程模型三个阶段知识要点第一节 Android启动概括、第二节 init.rc解析、第三节 Zygote、第四节 面试题第二章 跨进程通信IPC解析Binder作为Android进程间通信的机制可以看做是一个驱动。在Android中常见的进程间通信例如系统类的打电话、闹钟等自己创建的像WebView、视频播放、音频播放、大图浏览等。第三章 Handler源码解析第一节 源码分析第二节 难点问题第三节Handler常问面试题有需要的朋友扫描下方二维码领取同时这里还搭建了一个基于chatGPT的微信群聊机器人24小时为大家解答疑难技术问题。