android开发-android的消息机制(Handler)源码解析

android的消息机制其实就是Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程
Handler的主要作用是讲一个任务切换到某个指定的线程中去执行
android规定访问UI只能在主线程中进行,如果在子线程中访问UI 那么程序会抛出异常。
ViewRootImpl对UI操作做了验证,这个验证的工作是由ViewrootImpl的checkThead
void checkThead(){
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
所以必须在主线程中访问UI 但是android又不建议在主线程中做耗时的操作,否则导致ANR。
我们这时候就需要在子线程中进行耗时操作,获取完结果我们必须在主线程中显示ui
如果没有Handler 我们是无法玩成这样的工作的,系统提供Handler也是为了解决子线程中无法访问UI的问题


为什么系统不让子线程访问UI呢
因为android的UI控件不是线程安全的,如果在多线程中并发访问,准定会代理不可预期的问题
系统为什么不加上锁呢
缺点两个:1、加上锁会让UI访问的逻辑变的复杂。2、锁机制会降低UI访问效率,因为锁会阻塞一些线程的执行
所以最简单高效的方法就是采用单线程模型来处理UI,对开发者也不是很麻烦 只通过Handler切换一下UI访问的执行线程而已


Handler创建时会采用当前线程的Looper来构建内部的消息循环系统,如果当前的线程没有Looper那么就会报错的
因为Handler 发送、接受的消息 都是通过Looper来管理的,Looper里面有一个消息队列MessageQueue。
MessageQueue本质并不是队列,内部封装了一个单向链表数据结构来围护消息列表,单链表在插入和移除上有优势。它里面有两个方法,enqueueMessage和next,enqueueMessage负责向队列添加消息,而next负责取出消息并从消息队列里面移除。


Handler的post方法本质还是send,handler将Message消息投递到Handler内部的Looper中去处理。
这个send方法内部就是调用MessageQueue的enqueueMessage方法 将这个消息放入消息队列中,然后Looper发现有新消息到来 就会处理这个消息,这个Message中的target就是我们的handler,Looper会调用这个handler中的handlerMessage方法。


注意Looper是运行在创建Handler所在的线程(我们也可以给我们的Handler赋值一个Looper)
这样一来业务的逻辑就被切换到创建Handler所在的线程中去了。
无论消息是在哪个线程被添加到MessageQueue的,处理MessageQueue中的业务逻辑的还是最开始创建的线程!


Handler的工作需要Looper,没有Looper的线程就会报错,那么怎么开启一个Looper呢
Looper.prepare()为当前线程创建一个looper,而开启消息循环是looper.loop();
new Thread(){
 public void run(){
Looper.prepare();
Hanedler handler=new Handler();
Looper.loop();
}
}
Looper还提供了prepareMainLooper的方法,这个方法主要是给主线程,也就是ActivityThread创建Looper使用的,本质还是prepare方法,由于主线程的Looper比较特殊,所以Looper还提供了一个getMainLooper的方法,通过它可以在任何地方获取主线程的Looper


Looper还可以退出,调用quit或者quitSafely,他们区别是quite是直接退出,而quitSafely会先打一个退出的标记,然后等待消息都处理完毕之后才安全的退出
Looper退出之后,那么handler 发送send方法都会返回false


android主线程就是ActivityThread 主线程的入口方法为main,在main方法中系统通过Looper.prepareMainLooper() 来创建主线程的Looper以及MessageQueue,并通过Looper.loop()开启主线程的消息循环


比较好的文章

http://www.jianshu.com/p/c39203884209

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值