handle原理

handle原理

  • handler 总体概述
    • 使用场景 线程通信
    • handler 四个对象 handler message, messagequeue looper
  • 总体流程图
    • 总体流程图

    • handler使用的流程图

    • handler原理图

  • UML类图

  • handler
    • 作用
      • 线程间通信
      • 通过runnable 回调进行消息处理
    • handler 初始化的时候都做了什么工作
      • 获取当前线程的looper实例,然后和looper的messagequeue 进行关联
      • handler初始化的时queue和looper的queue进行关联

    • handler 的sendMessage的代码调用链

    • handler的post方法代码调用链

    • hander 的enqueueMessage方法 (把当前handler对象给message.target)

  • looper
    • 作用 :用来循环读取messagequeue消息然后交给handler进行消息处理
  • message
    • 作用 :存放消息
    • message对象里面的成员

  • messagequeue
    • 作用 :组织message消息
    • 底层使用的是单链表
  • ThreadLocal
    • 特性:提供线程的局部变量 ,实现了线程的数据隔离
    • 在Handler中使用的 使用ThreadLocal 目的是为了保证一个线程里面只有一个looper对象
  • Android提供了实现Handler的类和方法
    • activity的runOnUiThread()方法
    • View.post()方法
    • HandlerThread类
    • AsyncTask
  • 常见面试题
    • 问题:能说一下android handler 的原理吗
      • 简答 android 当UI线程启动的时候 会首先创建一个looper对象和looper绑定的messagequeue对象 looper不断的从messahequeue里面取message 然后交给handler的handlermessage方法进行消息处理
    • 问题:主线程的looper和子线程的looper有什么不同
      • 主线程的looper 不能退出循环,子线程的可以,主线程的looper在创建的时候传递的quitAllowed为false
    • message 一些问题
      • 问题message 创建的方式有几种 有什么区别
        • 两种
          • 方式1 new Message
          • 方式2 使用 Message.obtain 获取一个Message对象(Message 类里有一个静态变量sPool (消息池)是从消息池里面进行获取)
          • 问题 : message 使用之后做了什么处理
            • 回答: message 被loop消费之后进行数据的擦除 调用recycleUnchecked方法
              • loop方法消费message

              • 调用Message的recycleUnChecked方法进行擦除数据

      • 问题 :message 的数据结构是什么
        • 回答 单向列表 message 通过next 来持有下一个对象的引用 典型的是链表结构
    • 问题:每个线程只有唯一的一个loooper andorid 是如何保证这一点呢
      • 回答: 使用ThreadLocal 来保存一个线程只有一个looper的 ThreadLocal的key 就是当前线程 value 就是looper 使用ThreadLocal 核心是一个hashMap 这个特性
      • 扩展问题 哪messageQueue 如何保证唯一呢?
        • 回答: 因为messageQueue 是looper 的成员变量 Looper 唯一 哪messageQueue肯定也是惟一的
    • 问题:looper 如何保证不断的从messagequeue 取数据的
      • 回答 Looper的loop 方法里面有有for()死循环 不断的从Messagequeue里面取出message进行处理
    • 问题 :UI线程创建了Looper 若是死循环 哪不是一直占用CPU的资源吗
      • 回答: 这个循环比较特殊 queue.next 是一个线程阻塞的操作 会交出cpu的执行时间权 这样就不至于出现卡顿或则ANR
    • 问题:如何使用handler进行线程之间通信 子线程和ui线程 ,子线程和子线程.
      • 具体可以参考 HandlerThread
    • 问题: 一个线程有几个 Handler?
      • 答:一个线程可以用有多 Handler,因为 Handler 最终是被 Message 持用的(post 里面的 Runnable 最终也会被包装成一个 Message),以便 Looper 在拿到 Message 后调用 Handler 的 dispatchMessage 完成回调,而且项目中仔细去看也确实如此,我们可以每个 Activity 中都创建一个 Handler 来处理回调到主线程的任务。
    • 问题 :quit和quitsafely有什么区别
      • 回答: 当调用looper的quit方法的时候,实际是调用的是messagequeue removeAllmessageLocked方法,方法的作用是清空Messagequeue里面的所有的message 注意是全部 ,当使用quitSalfy方法时调用的是messagequeueu的 removeAllFutureMessageLocked方法 ,这个方法只会清除所有延时消息,非延时的消息派发之后 looper 就不在接收消息了 消息的循环就介绍了
    • 问题:Looper 死循环为什么不会导致应用卡死?
      •  
      • 简单说就是在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce()方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质同步I/O,即读写是阻塞的。 所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。 Gityuan–Handler(Native层)
  • 总结
    • new Handler的时候Handler就已经拿到了线程的Looper 。MessagQueue
    • handler发送消息:
      • 把Handler保存到Message里。
      • 把Message保存到messageQueue里。
    • ActivityThread.java主线程入口类
      • 在main()方法中存入了Looper.prepareMainLooper();(这里已经创建了Looper,messagequeue)然后不断地执行获取消息的方法:Looper.loop();去出message,然后调用handler的dispatchMessage(msg);
  • 参考
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值