前言: 很早以前,学习android的时候就接触过Handler ,知道Handler是一个用于线程间通信的类,最常用于做下载条,最近,看了Pro android 3 这本书,里面描述的Handler 说得非常的细致,与此,写下Handler的学习笔记

Android 运行的进程

为了,更好的了解Handler的机制,我们应该首先,将Android系统整个运行进程都要烂熟于心,下面是android 进程运行图:

从图中我们可以看到,当我们从外部调用组件的时候,Service 和 ContentProvider 是从线程池那里获取线程,而Activity 和BroadcastReceiver是直接在主线程运行,为了,追踪线程,我们可以用debug 方法,或者使用一个工具类,这里,我们创建一个用于监视线程的工具类

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 /** * @author Tom_achai * @ date 2011-11-20 * */ public class Utils { public static long getThreadId(){ Thread t = Thread.currentThread(); return t.getId(); } /** * 获取单独线程信息 * @ return */ public static String getThreadSignature(){ Thread t = Thread.currentThread(); long l = t.getId(); String name = t.getName(); long p = t.getPriority(); String gname = t.getThreadGroup().getName(); return ( "(Thread):" +name+ ":(id)" + l + "(:priority)" + p + ":(group)" + gname ); } /** *获取当前线程 信息 */ public static void logThreadSignature(){ Log.d( "ThreadUtils" , getThreadSignature()); } public static void logThreadSignature(String name ){ Log.d( "ThreadUtils" , name + ":" +getThreadSignature()); } public static void sleepForInSecs(int secs){ try{ Thread. sleep (secs * 1000); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } /** * 讲String放进Bundle 中 * @param message * @ return */ public static Bundle getStringAsBundle(String message){ Bundle b = new Bundle(); b.putString( "message" , message); return b; } /** * * 获取Bundle的String * @param b * @ return */ public static String getStringFromABundle(Bundle b){ return b.getString( "message" ); } }

有了这样一个类就可以方便我们观察线程的运行

好了,现在准备好以后就进入正题Handler

Handlers

为什么要使用Handlers?

因为,我们当我们的主线程队列,如果处理一个消息超过5秒,android 就会抛出一个 ANP(无响应)的消息,所以,我们需要把一些要处理比较长的消息,放在一个单独线程里面处理,把处理以后的结果,返回给主线程运行,就需要用的Handler来进行线程建的通信,关系如下图;

下面是Handler,Message,Message Queue 之间的关系图

这个图有4个地方关系到handlers

1, 主线程(Main thread)

2, 主线程队列(Main thread queue)

3,Hanlder

4,Message

上面的四个地方,主线程,和主线程的队列我们无需处理,所以,我们主要是处理Handler 和 Message 之间的关系.

我们每发出一个Message,Message就会落在主线程的队列当中,然后,Handler就可以调用Message绑定的数据,对主线程的组件进行操作.

Message

作为handler接受的对象,我们有必要知道Message这个数据类型是个怎样的数据类型

从官方文档中我们可以知道message 关于数据的字段

public int what
public int arg1
public int arg2
public Object obj

从上面的表格可以看出,message 提供了一个对象来存储对象,而且,还提供了三个int字段用来存储少量int类型

当然,除了以上三个Message 自有的字段外,我们还可以通过setData(Bundle b),来存储一个Bundle对象,来存储更丰富的数据类型,例如,图片等等.

在初始化我们的message的时候就可以为我们的Message默认字段赋值,注意赋值顺序!!!

1 2 3 4 5 6 7 8 9 Message msg = obtainMessage(); // 设置我们what 字段的初值,注意顺序!!! Message msg = mHandler.obtainMessage(int what); // 下面同理 Message msg = mHandler.obtainMessage(int what,Object object); Message msg = mHandler.obtainMessage(int what,int arg1,int arg2); Message msg = mHandler.obtainMessage(int what,int arg1,int arg2, Object obj );



二;

handler机制的原理

andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。

4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。

1.Handler创建消息

每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图所示。


2.Handler发送消息

UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。

Handler、Looper、MessageQueue的初始化流程如图所示:


Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。

3.Handler处理消息

UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。

子线程通过Handler、Looper与UI主线程通信的流程如图所示。



更多相关文章

  1. Handler&Looper
  2. android 仿QQ界面
  3. 【Android】Thread与Service的差异
  4. 浅谈Android(安卓)ANR在线监控原理
  5. 如何避免android ANR
  6. Android(安卓)2.3.3 NFC分析
  7. Android(安卓)Notification 用法的4种形式
  8. Android(安卓)UI界面刷新与交互
  9. android 中定时器的几种用法总结

随机推荐

  1. php的Snoopy类案例讲解
  2. 意派Epub360丨如何做好金三银四招聘H5?来
  3. TP6 MVC 基础、中间键
  4. 初学者怎么画Q版人物?q版漫画人物绘画学习
  5. 意派Epub360丨火力全开!趣味H5助力HR玩转
  6. 数据库语句的拼凑查询
  7. PHP变量和数组遍历以及初始函数
  8. 给R语言RStudio添加阿里云镜像源
  9. Android快速开发-选项卡
  10. Android下pm 命令详解