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
-
- 主线程的looper 不能退出循环,子线程的可以,主线程的looper在创建的时候传递的quitAllowed为false
- message 一些问题
- 问题message 创建的方式有几种 有什么区别
- 两种
- 方式1 new Message
- 方式2 使用 Message.obtain 获取一个Message对象(Message 类里有一个静态变量sPool (消息池)是从消息池里面进行获取)
-
- 问题 : message 使用之后做了什么处理
- 回答: message 被loop消费之后进行数据的擦除 调用recycleUnchecked方法
- loop方法消费message
- 调用Message的recycleUnChecked方法进行擦除数据
- loop方法消费message
- 回答: message 被loop消费之后进行数据的擦除 调用recycleUnchecked方法
- 两种
- 问题 :message 的数据结构是什么
- 回答 单向列表 message 通过next 来持有下一个对象的引用 典型的是链表结构
-
- 回答 单向列表 message 通过next 来持有下一个对象的引用 典型的是链表结构
- 问题message 创建的方式有几种 有什么区别
- 问题:每个线程只有唯一的一个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层)
- 问题:能说一下android handler 的原理吗
- 总结
- new Handler的时候Handler就已经拿到了线程的Looper 。MessagQueue
- handler发送消息:
- 把Handler保存到Message里。
- 把Message保存到messageQueue里。
- ActivityThread.java主线程入口类
- 在main()方法中存入了Looper.prepareMainLooper();(这里已经创建了Looper,messagequeue)然后不断地执行获取消息的方法:Looper.loop();去出message,然后调用handler的dispatchMessage(msg);
-
- 参考