Android消息机制(1)----简单介绍

什么是Handler?

​ Handler是Android消息机制的上层接口,所以开发者在开发过程中只需要和Handler交互即可。Handler的使用过程很简单,通过它可以轻松的将一个任务切换到Handler的所在的线程中去执行。很多人认为Handler的作用是更新UI,这的确没错,但是本质上来说,Handler并不是专门用于更新UI的,他只是常被开发者用来更新UI。

Handler的消息机制

​ Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。MessageQueue的中文翻译是消息队列,顾名思义,它的内部存储了一组信息,以队列的形式对外提供插入和删除的工作。虽然叫消息队列,但是它的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表。Looper的中文翻译为循环,在这里可以理解为消息循环。由于MessageQueue是一个消息队列,他不能去处理信息,所以引入Looper这个东西来填补功能。Looper会以无限循环的形式去查找是否有新消息,如果有的话就处理消息,否则就一直等待MessageQueue中的消息,处于一个等待状态。ThreadLocal是Looper中的一个新的概念,ThreadLocal并不是一个线程,它的作用是可以在每个线程中存储数据。

​ 在Handler创建的时候会采用当前线程的Looper来构造消息循环系统,那么Handler内部如何获取到当前线程的Looper?这时候就要使用ThreadLocal,ThreadLocal可以在不同的线程中互不干扰的存储并提供数据,通过这个ThreadLocal我们可以获取到每个线程的Looper。Handler的运行机制、MessageQueue的工作流程、Looper的工作流程这三个东西其实是一个整体。Handler的主要作用是将一个任务切换到某个指定的线程中执行。

注意:线程默认是没有Looper的,如果我们要使用Handler就要为线程创建一个Looper。但是有一个线程不同,那就是主线程(UI线程),就是ActivityThread,在主线程ActivityThread创建时,就会自动初始化Looper,所以我们在主线程中可以默认的使用Handler的原因。

为什么不能在子线程更改UI

​ 对于每一个学Android的人,都会经历一个共同的问题,那就是为什么Android规定访问UI只能在主线程中进行,如果在子线程中访问UI,那么程序就会抛出异常。下面说一下原因:

​ 在View的源码中,我们知道绘制View是从ViewRoot来开始的,而ViewRoot对应于ViewRootImpl类,ViewRootImpl中不仅对UI进行操作,而且还对UI操作进行了验证,这个验证工作是由ViewRootImpl的checkThread方法来完成,如下:

void checkThread(){
    if(mThread != Thread.currentThread()){
        throw new CalledFromWrongThreadException(
        	"Only the original thread that created a view hierarchy can touch its views."
        )
    }
}

为什么要进行这个验证呢?

  • Android的UI线程是线程不安全的,如果在多线程中并发访问可能会导致UI控件处于一个不可预期的状态。
  • 非线程安全不能加Lock线程锁,否则会阻塞其他线程对View的访问,效率就会变得低下。
  • 主线程负责更新,子线程负责耗时操作,能够大大提升响应效率。
  • 主线程进行耗时操作,很容易导致程序无法响应即ANR问题。

所以综上,我们要采用单线程模型来处理UI操作,对于开发者来说,我们就可以通过Handler切换一下UI的访问线程。

Handler的简单工作流程

​ 在Handler创建完毕后,其内部的Looper和MessageQueue就可以和Handler协同操作了。

通过Handler的post方法将一个Runnable投递到Handler内部的Looper中心去处理,也可以通过Handler的send方法来发送一个信息,来让这个消息也同样会在Looper中处理。当Handler的send方法被调用时,它会调用MessageQueue的enqueueMessage方法将这个消息放入队列中,然后Looper发现有新消息到来,就会处理这个消息,最终消息中的Runnable或者Handler的handleMessage方法就会被调用。由于Loop是运行在创建Handler的线程当中,所以Handler的业务逻辑就被切换到创建到Handler的线程中去执行了。

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值