网站开发3687474企鹅,drupal joomla wordpress 移动设备,河津网站建设网站建设,网页设计属于平面设计吗第10章 Android的消息机制 10.1 Android消息机制概述 (1)Android的消息机制主要是指Handler的运行机制#xff0c;其底层需要MessageQueue和Looper的支撑。MessageQueue是以单链表的数据结构存储消息列表但是以队列的形式对外提供插入和删除消息操作的消息队列。MessageQueue只…第10章 Android的消息机制 10.1 Android消息机制概述 (1)Android的消息机制主要是指Handler的运行机制其底层需要MessageQueue和Looper的支撑。MessageQueue是以单链表的数据结构存储消息列表但是以队列的形式对外提供插入和删除消息操作的消息队列。MessageQueue只是消息的存储单元而Looper则是以无限循环的形式去查找是否有新消息如果有的话就去处理消息否则就一直等待着。(2)Handler的主要作用是将一个任务切换到某个指定的线程中去执行。为什么要提供这个功能呢Android规定UI操作只能在主线程中进行ViewRootImpl的checkThread方法会验证当前线程是否可以进行UI操作。为什么不允许子线程访问UI呢这是因为UI组件不是线程安全的如果在多线程中并发访问可能会导致UI组件处于不可预期的状态。另外如果对UI组件的访问进行加锁机制的话又会降低UI访问的效率所以还是采用单线程模型来处理UI事件。(3)Handler的创建会采用当前线程的Looper来构建内部的消息循环系统如果当前线程中不存在Looper的话就会报错。Handler可以用post方法将一个Runnable投递到消息队列中也可以用send方法发送一个消息投递到消息队列中其实post最终还是调用了send方法。 10.2 Android的消息机制分析 (1)ThreadLocal的工作原理1.ThreadLocal是一个线程内部的数据存储类通过它可以在指定的线程中存储数据数据存储以后只有在指定线程中可以获取到存储的数据对于其他线程来说则无法获取到数据。一般来说当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候可以考虑使用ThreadLocal。 对于Handler来说它需要获取当前线程的Looper而Looper的作用域就是线程并且不同线程具有不同的Looper这个时候通过ThreadLocal就可以实现Looper在线程中的存取了。2.ThreadLocal的原理不同线程访问同一个ThreadLocal的get方法时ThreadLocal内部会从各自的线程中取出一个数组然后再从数组中根据当前ThreadLocal的索引去查找出对应的value值不同线程中的数组是不同的这就是为什么通过ThreadLocal可以在不同线程中维护一套数据的副本并且彼此互不干扰。3.ThreadLocal是一个泛型类public class ThreadLocalT下面是它的set方法 public void set(T value) { Thread currentThread Thread.currentThread(); Values values values(currentThread); if (values null) { values initializeValues(currentThread); } values.put(this, value);} Values是Thread类内部专门用来存储线程的ThreadLocal数据的它内部有一个数组private Object[] tableThreadLocal的值就存在这个table数组中。如果values的值为null那么就需要对其进行初始化然后再将ThreadLocal的值进行存储。ThreadLocal数据的存储规则ThreadLocal的值在table数组中的存储位置总是ThreadLocal的索引1的位置。 (2)MessageQueue的工作原理1.MessageQueue其实是通过单链表来维护消息列表的它包含两个主要操作enqueueMessage和next前者是插入消息后者是取出一条消息并移除。2.next方法是一个无限循环的方法如果消息队列中没有消息那么next方法会一直阻塞在这里。当有新消息到来时next方法会返回这条消息并将它从链表中移除。 (3)Looper的工作原理1.为一个线程创建Looper的方法代码如下所示 new Thread(test){ Override public void run() { Looper.prepare();//创建looper Handler handler new Handler();//可以创建handler了 Looper.loop();//开始looper循环 }}.start(); 2.Looper的prepareMainLooper方法主要是给主线程也就是ActivityThread创建Looper使用的本质也是调用了prepare方法。3.Looper的quit和quitSafely方法的区别是前者会直接退出Looper后者只是设定一个退出标记然后把消息队列中的已有消息处理完毕后才安全地退出。Looper退出之后通过Handler发送的消息就会失败这个时候Handler的send方法会返回false。在子线程中如果手动为其创建了Looper那么在所有的事情完成以后应该调用quit方法来终止消息循环否则这个子线程就会一直处于等待的状态而如果退出Looper以后这个线程就会立刻终止因此建议不需要的时候终止Looper。4.Looper的loop方法会调用MessageQueue的next方法来获取新消息而next是一个阻塞操作当没有消息时next方法会一直阻塞着在那里这也导致了loop方法一直阻塞在那里。如果MessageQueue的next方法返回了新消息Looper就会处理这条消息msg.target.dispatchMessage(msg)其中的msg.target就是发送这条消息的Handler对象。 (4)Handler的工作原理1.Handler就是处理消息的发送和接收之后的处理2.Handler处理消息的过程 public void dispatchMessage(Message msg) { if (msg.callback ! null) { handleCallback(msg);//当message是runnable的情况也就是Handler的post方法传递的参数这种情况下直接执行runnable的run方法 } else { if (mCallback ! null) {//如果创建Handler的时候是给Handler设置了Callback接口的实现那么此时调用该实现的handleMessage方法 if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg);//如果是派生Handler的子类就要重写handleMessage方法那么此时就是调用子类实现的handleMessage方法 }}private static void handleCallback(Message message) { message.callback.run();}/** * Subclasses must implement this to receive messages. */public void handleMessage(Message msg) {} 3.Handler还有一个特殊的构造方法它可以通过特定的Looper来创建Handler。 public Handler(Looper looper){ this(looper, null, false);} 4.Android的主线程就是ActivityThread主线程的入口方法就是main其中调用了Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue并通过Looper.loop()方法来开启主线程的消息循环。主线程内有一个Handler即ActivityThread.H它定义了一组消息类型主要包含了四大组件的启动和停止等过程例如LAUNCH_ACTIVITY等。ActivityThread通过ApplicationThread和AMS进行进程间通信AMS以进程间通信的方法完成ActivityThread的请求后会回调ApplicationThread中的Binder方法然后ApplicationThread会向H发送消息H收到消息后会将ApplicationThread中的逻辑切换到ActivityThread中去执行即切换到主线程中去执行这个过程就是主线程的消息循环模型。 OK本章结束谢谢阅读。转载于:https://www.cnblogs.com/dongweiq/p/5029036.html