前一阵子在和一位技术总监闲谈中了解到,现在 Android Framework 成为头部公司必不缺少的技术栈]之一,尤其是熟悉 Franmework 源码的 Android 开发者,在面试中往往会占到很大的优势

那我今天就带来一部分有关:Framework 比较高刷的 Handler&Binder 两块技术点面试题分享

framework面试题 Android android framework开发面试_ui

Handler 篇

looper,loop() 为什么不会阻塞主线程?
  • 因为主线程的 Looper 是在 ActivityThread 里面准备出来,创建出来的,那么其实我们 Android 程序也就是 Java 程序,你启动它,进入 main 方法,执行完所有的方法,也就会退出了
  • 我们写的代码就是通过 Handler 驱动起来的,我们 Activity 的 onCreate、onResume、onStop 等等这些生命周期方法,包括我们的 UI 绘制的信号,这些UI绘制的事件都是通过 Handler Looper 循环内部发起的,来调用回调我们的各个 Activity,各个 Fragment 等等这样的一些组件里面的各个生命周期方法,我们的代码就是在循环里面执行的,所以不会阻塞
简述 Handler 的实现原理
  • Android 应用是通过消息驱动运行的,在 Android 中一切皆消息,包括触摸事件,视图的绘制、显示和刷新等等都是消息
  • Handler 是消息机制的上层接口,平时开发中我们只会接触到 Handler 和 Message,内部还有 MessageQueue 和 Looper 两大助手共同实现消息循环系统。
延迟消息是怎么实现的?
  • 无论是即时消息还是延迟消息,都是计算出具体的时间,然后作为消息的 when 字段进程赋值
  • 在 MessageQueue 中找到合适的位置(安排 when 小到大排列),并将消息插入到 MessageQueue 中;这样, MessageQueue 就是一个按照消息时间排列的一个链表结构
为什么 Handler 会报内存泄漏?
  • 因为是内部类持有外部类的对象, sendMessage 的时候会调用到 Handler 的 enqueueMessage 方法,msg.target = this; Message 会持有 handler,而 handler 持有调用 handler 的对象,所以 gc 不能回收

Binder 篇

Binder 的定向制导,如何找到目标 Binder,唤起进程或者线程呢?

Binder 实体服务其实有两种:

  • 一是通过 addService 注册到 ServiceManager 中的服务,比如 ActivityManagerService、PackageManagerService、PowerManagerService 等,一般都是系统服务;
  • 还有一种是通过 bindService 拉起的一些服务,一般是开发者自己实现的服务

这里先看通过 addService 添加的被 ServiceManager 所管理的服务

ServiceManager 是比较特殊的服务,所有应用都能直接使用,因为 ServiceManager 对于 Client 端来说 Handle 句柄是固定的,都是 0,所以 ServiceManager 服务并不需要查询,可以直接使用

Binder 为什么会有两棵 binder_ref 红黑树?
  • Binder_proc 中存在两棵 binder_ref 红黑树,其实两棵红黑树中的节点是复用的,只是查询方式不同,一个通过 Handle 句柄,一个通过 node 节点查找
  • refs_by_node 红黑树主要是为了 Binder驱动往用户空间写数据所使用的,而 refs_by_desc 是用户空间向 Binder 驱动写数据使用的,只是方向问题

比如在服务 addService 的时候,binder 驱动会在在 ServiceManager 进程的 binder_proc 中查找 binder_ref 结构体

Binder 是如何做到一次拷贝的

  • 用户空间虚拟内存地址映射物理内存中的
  • 虚拟内存读写实际上是对物理内存读写,这个过程就是内存映射

这个内存映射过程是通过系统调用 mmap() 来实现的 Binder借助了内存映射的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射,就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝

Binder机制是如何跨进程的

  • 在内核空间创建一块接收缓存区,
  • 实现地址映射:将内核缓存区、接收进程用户空间映射到同一接收缓存区

发送进程通过系统调用(copy_from_user)将数据发送到内核缓存区;由于内核缓存区和接收进程用户空间存在映射关系,故相当于也发送了接收进程的用户空间,实现了跨进程通信

就举例这么多了面试题也不是几个就能全部覆盖的,毕竟面试官不是吃素的,他会换着花样问你;有想跳槽拿高薪Android 开发的朋友,我这里分享一份 Handler、Binder 精选面试 PDF 文档私信发送 “面试” 直达获取;想拿高薪的人很多,就看你肯不肯努力了

面试题 PDF 文档内容展示:

Handler 机制之 Thread

framework面试题 Android android framework开发面试_java_02

Handler 机制之 ThreadLocal

framework面试题 Android android framework开发面试_ui_03

Handler 机制之 SystemClock 类

framework面试题 Android android framework开发面试_android_04

Handler 机制之 Looper 与 Handler 简介

framework面试题 Android android framework开发面试_面试_05

Android 跨进程通信 IPC 之 Binder 之 Framewor k层 C++ 篇

framework面试题 Android android framework开发面试_面试_06

Android 跨进程通信 IPC 之 Binder 之 Framework 层 Java 篇

framework面试题 Android android framework开发面试_android_07

Android 跨进程通信 IPC 之 Binder 的补充

framework面试题 Android android framework开发面试_ui_08

Android 跨进程通信 IPC 之 Binder 总结

framework面试题 Android android framework开发面试_binder_09