Handler 常见的问题以及底层原理分析

1. Handler 作用
  1. 原理 Handler通过sendMessage发送消息,将消息放入MessageQueue中,在MessageQueue中通过时间的维度来进行排序,Looper通过调用loop方法不断的从MessageQueue中获取消息,执行HandlerdispatchMessage,最后调用handleMessage方法。
  1. 来源 因为Android中主线程是不能进行耗时操作的,子线程是不能进行更新UI。所以就有handler,它的作用就是实现线程之间的通信。 handler整个流程中,主要有四个对象,handlerMessage, MessageQueue,Looper。当APP应用启动创建的时候,就会在主线程中创建handler对象, 我们通过要传送的消息保存到Message中,handler通过调用sendMessage方法将Message发送到MessageQueue中,Looper对象就会不断的调用loop ()方法 不断的从MessageQueue中取出Message交给handler进行处理。来实现线程之间的通信。
2. Handler、Looper、MessageQueue、线程的关系
  • 一个线程只会有一个Looper对象,所以线程和Looper是一一对应的。MessageQueue对象是在new Looper的时候创建的,所以LooperMessageQueue是一一对应的。
    Handler的作用只是将消息加到MessageQueue中,并后续取出消息后,根据消息的target字段分发给当初的那个handler,所以Handler对于Looper是可以 多对一的,也就是多个Hanlder对象都可以用同一个线程、同一个Looper、同一个MessageQueue
  • 总结:LooperMessageQueue、线程是一一对应关系,而他们与Handler是可以一对多
3. Handler 的底层实现原理?
  1. 理解handler的实现原理,最重要的是理解Looper的实现原理,Looper才是实现handler机制的核心。任何一个handler在使用sendMessage或者post时候,都会先构造一个Message,并把自己放到message中,然后把Message放到对应的LooperMessageQueueLooper通过控制MessageQueue来获取message执行其中的handler或者runnable。 要在当前线程中执行handler指定操作,必须要先看当前线程中有没有looper,如果有looper,handler就会通过sendMessage,或者post先构造一个message,然后把message放到当前线程的looper中,looper会在当前线程中循环取出message执行,如果没有looper,就要通过looper.prepare()方法在当前线程中构建一个looper,然后主动执行looper.loop()来实现循环。
  2. 梳理四条关键点:
    1、每一个线程中最多只有一个Looper,通过ThreadLocal来保存,Looper中有Message队列,保存handler并且执行handler发送的message。
    2、在线程中通过Looper.prepare()来创建Looper,并且通过ThreadLocal来保存Looper,每一个线程中只能调用一次Looper.prepare(),也就是说一个线程中最多只有一个Looper,这样可以保证线程中Looper的唯一性。
    3、handler中执行sendMessage或者post操作,这些操作执行的线程是handler中Looper所在的线程,和handler在哪里创建没关系,和Handler中的Looper在那创建有关系。
    4、一个线程中只能有一个Looper,但是一个Looper可以对应多个handler,在同一个Looper中的消息都在同一条线程中执行。
4. Handler机制,sendMessage和post(Runnable)的区别?
  • post方法和handleMessage方法的不同在于:
    postrunnable会直接在callback中调用run方法执行,而sendMessage方法要用户主动重写mCallback或者handleMessage方法来处理。
5. Looper会一直消耗系统资源吗?
  • Looper不会一直消耗系统资源,当LooperMessageQueue中没有消息时,或者定时消息没到执行时间时,当前持有Looper的线程就会进入阻塞状态。looper阻塞肯定跟消息出队有关
6. Android的Handle机制,Looper关系,主线程的Handler是怎么判断收到的消息是哪个Handler传来的?
  • handler在sendMessage的时候会构建一个Message对象,并且把自己放在Message的target里面,这样的话Looper就可以根据Message中的target来判断当前的消息是哪个handler传来的。
7. Handler机制流程、Looper中延迟消息谁来唤醒Looper?
  • 在消息出队的for循环队列中会调用到下面的方法。
  nativePollOnce(ptr, nextPollTimeoutMillis);

  • 如果是延时消息,会在被阻塞nextPollTimeoutMillis时间后被叫醒,nextPollTimeoutMillis就是消息要执行的时间和当前的时间差。
8. Handler是怎么引起内存泄漏的?如何解决?
    1. 在Handler的handleMessage方法中(或者是run方法)处理消息,如果这个是一个延时消息,会一直保存在主线程的消息队列里,并且会影响系统对Activity的回收,造成内存泄露
    1. a. 在Handler的handleMessage方法中(或者是run方法)处理消息,如果这个是一个延时消息,会一直保存在主线程的消息队列里,并且会影响系统对Activity的回收,造成内存泄露
    1. b. 匿名内部类导致的泄露改为匿名静态内部类,并且对上下文或者Activity使用弱引用。
9. handler机制中如何确保Looper的唯一性?
  • Looper是保存在线程的ThreadLocal里面的,使用Handler的时候要调用Looper.prepare()来创建一个Looper并放在当前的线程的ThreadLocal里面。
      private static void prepare(boolean quitAllowed) {
          if (sThreadLocal.get() != null) {
              throw new RuntimeException("Only one Looper may be created per thread");
          }
          sThreadLocal.set(new Looper(quitAllowed));
      }

  • 可以看到,如果多次调用prepare的时候就会报Only one Looper may be created per thread,所以这样就可以保证一个线程中只有唯一的一个Looper
10. Handler 是如何能够线程切换,发送Message的?
  • handler的执行跟创建handler的线程无关,跟创建looper的线程相关,加入在子线程中创建一个Handler,但是Handler相关的Looper是主线程的,这样,如果handler执行post一个post,或者sendMessage,最终的handle Message都是在主线程中执行的。
11. Handler是如何切换线程的
  • 每个Looper都运行在对应的线程,所以不同的Looper调用的dispatchMessage方法就运行在其所在的线程了。
12. 为什么主线程的Looper是一个死循环,但是却不会ANR
  • 因为当Looper处理完所有消息的时候会进入阻塞状态,当有新的Message进来的时候会打破阻塞继续执行。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

在这里插入图片描述
二、源码解析合集
在这里插入图片描述

三、开源框架合集
在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值