android handler机制描述,Android的handler机制浅谈

handler机制能够说是android面试时必考的一项,其思想仍是比较nb的,最近和组内的ios同事聊天时,发现ios也有一套相似的机制,可见handler机制的重要性。在了解事后,作一个简单的总结,加深本身的印象。android

1、handler机制相关概念面试

在聊handler机制以前,咱们要先明确一些概念。

数据结构

一、主线程(UI线程)

oop

当程序第一次启动时,android会同时启动一条主线程(main thread),主线程主要用于处理UI相关事件spa

二、Message(消息)

.net

handler接收和处理的对象,经过获取message中携带的信息,作相关处理线程

三、ThreadLocal

对象

线程内部数据存储类,负责存储和获取本线程的looperblog

四、Message Queue(消息队列)

采用单链表的数据结构来存储消息列表,用来存放handler发出的message,遵循先进先出原则

五、handler(处理者)

Message的主要处理者,用来发送message和处理looper取出的message

六、Looper(循环器)

是MessageQueue和handler之间的桥梁,从MessageQueue取出消息给handler

2、Looper源码解析

主线程在activity启动时就建立好了,启动时回调用looper里的两个主要方法,prepareMainLooper和loop方法。

30d0440a1f59a9b87ba7dd05b1d69ea4.png

2de6a15a65a2a3de581d8ce0554845a8.png

能够看到,prepareMainLooper方法调用了prepare方法,而且调用后会检测sMainLooper是否为空,若是不为空则会抛异常。为空则经过myLooper方法来获取looper。而同时,prepare方法先检测了sThreadLocal里是否有looper,有则抛异常,没有则新set一个looper。可见在这个过程当中,要求sThreadLocal里是不容许有looper的,须要新建一个。从myLooper方法中能够看出,sMainLooper的looper正是取的新建立的looper。

17832dbaa4f5f6c1f6b776ddd462f11a.png

再看looper的构造方法,发如今里面new了一个消息队列,同时把当前线程做为数据持有。这张图里的这几个成员变量应该就是几个核心变量了。一个looper中,持有主looper,looper线程池,消息队列以及当前线程。

对于looper线程池,还要看下面这些源码。

128df1f44af6ca49fba90ffb2e506752.png

这是ThreadLocal的源码,泛型T接收的就是looper。经过这两个关键方法咱们能够看出,从looper线程池里获取loopera时,经过get方法。而ThreadLocal自己维护一个map,以线程为key,looper为value。当该线程做为key,没法从map中取出looper时,会调用setInitialValue方法,以该线程做为key,存放一个新建的value。而这个get方法告诉咱们,ThreadLocal是经过这种方式来维持每一个线程都有一个本身独立的looper。

3、Looper循环

老规矩,先上图,loop循环的源码比较长,截了两张图

602b0ba32c5c23f1debf85f27b4fe44e.png

93fb889d63230fe20a07574d60d2723e.png

能够看到,loop方法一开始先获取looper,以后获取looper中的message queue。以后是一个for无限循环,不断地从message queue中取消息。使用message queue中的next方法。

而MessageQueue中的next方法是取出本身维护的message链表的第一个,而后将后续的message在排列。

同时咱们注意到,取出的msg,会调用其本身target中的dispatchMessage方法。这个target,不少人应该想到,其实就是handler。handler与msg的绑定,是在handler发送msg时最终调用enqueueMessage时绑定的。而handler在建立时,就会经过Looper.mylooper方法获取当前线程的looper。而looper里又持有messageQueue。这样一切就都联系起来了。

4、整体流程

当咱们建立一个handler时,会调用looper的mylooper方法来得到当前线程的looper。若是没有,就会新建一个looper并存放在looper线程池里,保证每一个线程都有本身惟一的looper。而looper中持有MessageQueue,当新建一个Message时,经过handler发送时,会将这个Message存放到MessageQueue中,而loop方法一直在循环从messageQueue中取消息,发送的message会被取到,并处理。当发送了多个message时,会遵循先进先出原则维持在messageQueue中。那么,不一样线程中发送的message,最终是怎么在主线程中完成处理的呢。要从target的dispatchMessage方法中找答案。

5、主线程更新

39f4eb11979a1109b2523db24fcc4221.png

这是handler中dispatchMessage的源码,能够看到dispatchMessage的处理有三个优先级,先处理handleCallback方法,若是没有实现callback,则执行mCallback里的handleMessage方法,若是mCallback为空,则最终执行handler的handleMessage方法。这个方法在上面,一看居然为空。咱们恍然大悟,原来,这个不是咱们在建立handler时就重写的方法吗。

这下一切就都说得通了,handler是在主线程中建立的,其实现方法也是主线程中完成的,咱们的message绑定的handler是主线程中的,因此天然处理时就会到主线程中执行。那么有没有在线程中建立的handler的状况呢。有人试过会报错。不过我想经过主线程中的handler已经能够帮咱们解决大部分问题了,咱们只要在子线程中回调方法便可实现主线程刷新。

6、loop无线循环原理

若是一个looper无线循环,无论它是主线程中仍是子线程中,都会形成资源的浪费,以及耗时。那么为何loop方法可以一直循环呢。是由于loop在取不到消息时,会进入阻塞状态,该状态不会占用资源。这部分后续应该单独开一个线程的专题来详细解答。

好了,本篇handler机制写到这里就结束了,相信读者对于handler机制及流程,应该有一个大体的了解了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值