第十章、Android的消息机制

  1. Handler是Android消息机制的上层接口,使得我们在开发过程中只需要和Handler交互即可。
  2. Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层MessageQueue和Looper的支撑。
  3. MessageQueue的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息的列表。
  4. Looper会以无限循环的形式去查找是否有新的消息,如果有的话就去处理消息,否则一直等待。
  5. Looper中有一个特殊的概念,ThreadLocal,它的作用是可以在每个线程中存储数据。通过ThreadLocal可以获得每个线程的Looper,需要注意的是,线程是默认没有Looper的,如果需要使用Handler就必须为线程创建Looper。
  6. ActivityThread被创建时就会初始化Looper,这也是主线程中默认可以使用Handler的原因。

1. Android消息机制的概述

  1. Handler的主要作用是将一个任务切换到某个指定线程中去执行。
  2. Android的UI控件不是线程安全的,如果在多线程中并发访问可能 会导致UI处于不可预期的状态。
  3. 为什么不对UI控件加上锁机制?

    1. 加上锁机制会让UI访问的逻辑变得复杂
    2. 锁机制会降低UI访问的效率。
  4. Handler创建时会采用当前线程的Looper来构建内部的消息循环系统,如果当前线程没有Looper那么就会报错。解决方法就是在当前线程中创建Looper,或者在一个有Looper的线程中创建Handler。

  5. 调用Handler的post或者send方法时,Handler就会调用MessageQueue的enqueueMessage就会将这个消息放入消息队列中,然后Looper发现新消息到来时,就会处理这个消息。最终消息中的Runnable或者Handler的handleMessage方法就会被调用。
  6. Looper是运行在创建Handler所在的线程中的。
  7. Handler工作过程:

2.Android消息机制分析

1. ThreadLocal工作原理
  1. ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其它线程来说则无法获取到数据。
  2. 当数据是以线程为作用域并且不同线程具有不同的数据副本的时候,可以考虑使用ThreadLocal.
  3. ThreadLocal 另一个使用场景就是复杂逻辑下的对象传递,比如监听器的传递。
  4. 不通过线程中访问的是同一个ThreadLocal对象,但是它们通过ThreadLocal获取到的值确实一样的。之所以会这样,是因为不同线程访问同一个ThreadLocal的get方法,ThreadLoca内部会从各自的线程中取出一个数组,然后再从数据中根据当前ThreadLocal索引去查找对应的value值。所以不同线程中的数组是不同的。
  5. 从ThreadLocal的set和get方法可以看出,它们所操作的对象都是当前线程的localValues对象的table数组,因此在不同线程中访问同一个ThreadLocal的set和get方法,它们对ThreadLocal所做的读、写操作权限仅限于各自线程的内部,这就是为什么在多个线程中可以互不干扰地存储和修改数据。
2.消息队列的工作原理
  1. 消息队列在Android中指的是MessageQueue,MessageQueue主要包含两个操作:插入和读取。读取操作本身会伴随着删除操作。插入和删除分别对应enqueue和next。MessageQueue本身是通过一个单链表的数据结构来维护消息列表。
  2. enqueueMessage的作用是往消息队列中插入一条消息;next的作用是从消息队列中取出一条消息并将消息从队列中移除。
  3. next方法是一个无线循环的方法,如果消息队列中没有消息,那么next方法会一直堵塞在这里。当有新消息时,next方法会返回这条消息并将其从单链表中移除。
3.Looper的工作原理
  1. Looper在Android的消息机制中扮演者消息循环的角色,它会不停地从MessageQueue中查看是否有新的消息,如果有新的消息就会立刻处理,否则就一直阻塞在那里。
  2. 通过Looper.prepare()可以为当前线程创建一个Looper,通过Looper.loop()开启消息循环。
  3. prepareMainLooper方法,可以给ActivityThread创建Looper使用。
  4. 通过getMainLooper可以在任何地方获取到主线程的Looper。
  5. Looper可以退出,quit和quitSafely用来退出一个Looper。两者之间的区别:
    1. quit会直接退出Looper。
    2. quitSafely只是设定了一个退出标记,然后把消息队列中的已有消息处理完毕后才会安全退出。

  6. Looper退出后,通过Handler发送的消息会失败,这个时候Handler的send方法会返回false。如果Looper退出后,这个线程会立即终止。如果没有通过quit退出消息循环,那么这个子线程会一直处于等待状态。

4.Handler的工作原理
  1. Handler的主要工作包含消息的发送和接收过程,消息的发送可以通过post的一系列方法以及send的一些列方法来实现,post的一系列方法最终通过send的一系列方法来实现。
  2. Handler发送消息的过程仅仅是向消息队列中插入一条消息,MessageQueue的next方法就会返回这条消息给Looper,Looper收到消息后就开始处理了,最终消息由Looper交由Handler处理,即Handler的dispatchMessage就会被调用。

3. 主线程消息循环

  1. Android的主线程就是ActivityThread,主线程的入口方法为main,在main方法中系统会通过Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue,并通过Looper.loop()来开启主线程的消息循环。
  2. 主线程的消息循环开始后,ActivityThread还需要一个Handler来和消息队列进行交互,这个Handler就是Activity.H,它内部定义了一组消息类型,主要包含了四大组件的启动和停止等过程。
  3. AcitivityThread通过ApplicationThread和AMS进行进程间通信,AMS以进程间通的方式完成ActivityThread的请求后会回调ApplicationThread中的Binder方法,然后ApplicationThread会向H发送消息,H收到消息后会将ApplicationThread中的逻辑切换到ActivityThread中执行,切换到主线程中去执行。这个过程就是主线程的消息循环模型。

更多相关文章

  1. Android,谁动了我的内存(转)
  2. Android键盘系统
  3. Android(安卓)AsyncTask理解及简单用法
  4. Android开发规范详解
  5. Android推送通知指南
  6. 【Android】进程与线程基本知识
  7. android字体闪烁动画(线程)
  8. androidのview游戏框架
  9. Android应用程序键盘(Keyboard)消息处理机制分析(25)

随机推荐

  1. 【30篇突击 android】源码统计二
  2. Android ProgressDialog的使用
  3. 《Android程序运行过程,Android》
  4. Android资料
  5. Android SDK Manager无法自动更新
  6. ADT20新建项目Android Support library n
  7. mono for android 读取网络远程图片
  8. Android 删除手机联系人,添加手机联系人,更
  9. Android横竖屏切换
  10. ubuntu eclipse android搭建