企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### Android的消息机制 #### 一、取百家所长 附上网友关于本章的总结和归纳 [看云网友同学的总结](http://www.kancloud.cn/kancloud/art-of-android-development-reading-notes/90455),[amurocrash同学的总结](http://blog.csdn.net/amurocrash/article/details/48858353),[CSDN网友的归纳](http://blog.csdn.net/qy274770068/article/details/50931898) #### 二、总结归纳 #####1、 Handler的工作过程如图所示 * * * * * > **Handler的工作过程,图(page374),我简单概括一下就是:假设创建Handler的线程是A,耗时操作的线程是B,B线程中拿到handler实例发送消息或者post一个Runnable,实际是调用了MessageQueue的enqueueMessage方法,进入了消息队列,线程A中的Looper发现了这个消息,就会处理这个消息,也就是消息中的Runnable或者handler的handleMessage方法会被调用,这样handler中的业务逻辑就被切换到线程A中去了。** * * * * * **如图** ##### 2、ThreadLocal的工作原理 * * * * * **ThreadLocal我用一句大白话来讲解,就是看上去只new了一份,但在每个不同的线程中却可以拥有不同数据副本的神奇类。其本质是ThreadLocal中的Values类维护了一个Object[],而每个Thread类中有一个ThreadLocal.Values成员,当调用ThreadLocal的set方法时,其实是根据一定规则把这个线程中对应的ThreadLocal值塞进了Values的Object[]数组中的某个index里。这个index总是为ThreadLocal的reference字段所标识的对象的下一个位置。** * * * * * ##### 3、MessageQueue的工作原理 * * * * * **主要方法为enqueueMessage和next。 a. enqueueMessag主要就是一个单链表的插入操作, b. next方法是一个无限循环,如果消息队列中没有消息,next方法就阻塞,有新消息到来时,next方法会返回这条消息并将其从单链表中删除。** * * * * * ##### 4、Looper的工作原理 * * * * * **a. prepare方法,为当前没有Looper的线程创建Looper。 b. prepareMainLooper和getMainLooper方法用于创建和获取ActivityThread的Looper。 c. quit和quitSafely方法,前者立即退出,后者只是设定一个标记,当消息队列中的所有消息处理完毕后会才安全退出。子线程中创建的Looper建议不需要的时候都要手动终止。 d. loop方法,死循环,阻塞获取msg并丢给msg.target.dispatchMessage方法去处理,这里的target就是handler。** * * * * * ##### 5、Handler的工作原理: * * * * * **a. 无论sendMessage还是post最终都是调用的sendMessageAtTime方法。 b. 发送消息其实就是把一条消息通过MessageQueue的enqueueMessage方法加入消息队列,Looper收到消息就会调用handler的dispatchMessage方法。它的处理过程参考书page388的流程图,一看就懂~ c. 这里我补充一个东西,当我们直接Handler h = new Handler()时,本质调用的是Handler(Callback callback, Boolean async)构造方法,这个方法里会调用Looper.myLooper()方法,这个方法其实就是返回的ThreadLocal里保存的当前线程的Looper,这也就解释了为什么我们在主线程中这样new没有问题,子线程中如果不先Looper.prepare会抛出异常的原因,前面多次说了,因为ActivityThread会在初始化的时候创建自己的Looper。** * * * * *