一、Framework组件
1、说说你对Context的理解?
Context是一个抽象类,代表上下文环境
- Application Context
全局单例,适合:全局单例、工具类、长时间持有 Context
- Service Context
生命周期同 Service,不能弹 Dialog、不能操作 View
- Activity Context
有界面、有 Theme、可以弹 Dialog、可以操作 UI,但不能长时间持有,容易内存泄漏
2、ActivityThread工作原理?
一句话:
ActivityThread 就是应用进程的主线程管理类,它掌管 Looper、接收 AMS 指令、调度四大组件生命周期、处理所有 UI 事件。
你可以把它理解成:
App 进程的入口主类 + 主线程管家。
事件流程:AMS → Binder → ApplicationThread → mH Handler → ActivityThread.handleXX → 组件生命周期

final H mH = new H();
的查看方式参考android Framework
4、简单说下Android系统架构
Linux 内核:驱动、进程、内存、Binder
系统库 & ART:虚拟机、各种底层库(SQLite、OpenGL、Webkit、媒体库等)
Framework:四大组件、系统服务(AMS/PMS/WMS)
应用层:系统应用 + 第三方 App
AMS ------ ActivityManagerService
PMS ------ PackageManagerService
WMS ------ WindowManagerService
5、JVM、Art、Dalvik的区别、比较
JVM (Java Virtual Machine)
- 官方 Java 虚拟机,运行 Java/Kotlin 字节码(.class)
- 设计目标:跨平台、一次编译到处运行
- 适用:服务器、桌面、嵌入式(非 Android)
Dalvik (DVM)
- Google 为 Android 1.0--4.4 定制的虚拟机
- 针对 移动设备内存 / CPU 受限 优化
- 已废弃:Android 5.0 起被 ART 取代
ART (Android Runtime)
- Android 5.0+ 默认运行时,完全替代 Dalvik
- 核心改进:AOT 预编译 + 混合编译 + 全新 GC
- 目标:性能、流畅度、省电
二、view绘制
1、Requestlayout,onlayout,onDraw,DrawChild区别与联系?
- requestLayout 会触发 onMeasure + onLayout,可能触发 draw
- onLayout 是布局阶段,只摆位置
- onDraw 画自己
- drawChild 画孩子,由父 View 在 dispatchDraw 中调用
整体流程:
requestLayout → measure → layout → draw
onLayout 摆位置 → onDraw 画自己 → drawChild 画孩子
2、LinearLayout的onLayout方法实现解析(layoutVertical核心源码)
LinearLayout 垂直 layout 原理:
-
根据父 gravity 算起始 top
-
循环子 View,从上往下依次排列
-
每个子 View 位置:
- left 由 layout_gravity 决定
- top 是上一个底部位置
-
不断累加高度,形成垂直排列
3、View的绘制流程?
Android View 绘制流程分为三大步骤:
- onMeasure:自上而下递归测量所有 View 的宽高
- onLayout:父容器确定子 View 的位置
- onDraw:按照 "背景→自身→子 View→前景" 的顺序绘制到屏幕
requestLayout()
触发:measure + layout
不保证 draw
invalidate()
触发:draw
只重绘,不重新布局
postInvalidate()
子线程调用 invalidate
三、事件分发
安卓层级:Activity -> Window -> 根ViewGroup -> 子ViewGroup -> 子View
1、如何解决View的事件冲突?举个开发中遇到的例子?
内部拦截法
子 View 在 dispatchTouchEvent 中调用
java
getParent().requestDisallowInterceptTouchEvent(true/false);
告诉父容器:要不要拦截事件。
外部拦截法
父 View 重写 onInterceptTouchEvent
根据条件自己决定:是否拦截事件。
三、ipc通信
1、Binder框架中ServiceManager的作用?
ServiceManager 是 Binder 机制的服务管理中心:
- 维护系统服务的名称与 Binder 引用映射表
- 提供注册服务 和查询服务功能
- 是 Binder 通信的DNS 服务器
- 句柄固定为 0,是整个 Binder 架构的基础
2、为什么选择Binder?Binder机制的作用和原理?
Binder 驱动在内核空间开辟一块共享区域,通过 mmap 实现一次内存拷贝,把跨进程调用伪装成本地方法调用
共享内存性能最强但不安全、难用
Socket 通用但性能弱、无身份校验
管道 / 消息队列效率低、结构不适合 RPC
Binder 兼具:
- 一次拷贝高性能
- 内核 UID 安全校验
- C/S 架构适合 RPC
- 易用稳定,面向对象
3、讲讲AIDL?如何优化多模块都使用AIDL的情况?
AIDL = Android Interface Definition Language
安卓接口定义语言,用来快速生成 Binder 通信代码的工具。
本质就是:定义接口 → 自动生成 Proxy/Stub 代码,不用手写 Binder。
多模块 AIDL 优化思路
- 独立公共 AIDL 模块,统一维护接口
- 统一单个 IPC Service + 路由分发
- 合并请求,减少 IPC 次数
- 使用 oneway 异步调用
- 统一数据结构,减少序列化开销
- 统一死亡回调,避免内存泄漏
- 增加版本号兼容
4、Android中IPC方式、各种方式优缺点?为何需要IPC?多进程通信可能会出现的问题?
| 方式 | 性能 | 优点 | 缺点 |
|---|---|---|---|
| Binder/AIDL | 高 | 安全、易用、RPC | 略复杂 |
| Intent/ Bundle | 中 | 最简单 | 功能弱 |
| 文件共享 | 低 | 简单 | 不安全、不实时 |
| Messenger | 高 | 简单易用 | 串行、功能弱 |
| ContentProvider | 中 | 安全、系统级 | 较重 |
| Socket | 低 | 跨平台 | 开销大 |
| 共享内存 | 极高 | 最快 | 复杂、不安全 |
为何需要 IPC
内存隔离、功能隔离、系统通信、多 App 数据共享、申请更多内存。
多进程问题
静态变量失效、线程同步失效、SP 不可靠、Application 多次初始化、数据库不安全、内存增加。
4、AIDL理解
AIDL(Android Interface Definition Language):Android中用于定义进程间通信接口的一种语言(基于 Binder 的)。
饿了么HermesEventBus跨进程通信,本质也是AIDL通信
AIDL: 每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。而aidl就类似与两个进程之间的桥梁,使得两个进程之间可以进行数据的传输,跨进程通信有多种选择,比如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行。
5、Binder机制原理
Binder是Android中进程间通信的核心机制,它通过驱动层和框架层的配合实现进程间通信。Binder的工作原理如下:
- 服务端注册Binder对象:服务端通过Binder机制创建一个Binder对象,并将其注册到ServiceManager中,以便客户端可以通过Binder对象的引用来访问服务端。
- 客户端获取Binder对象:客户端通过ServiceManager获取服务端注册的Binder对象的引用。
- 客户端与服务端通信:客户端通过Binder对象的引用调用服务端提供的方法,实现进程间通信。
- 跨进程通信:Binder在内核层通过驱动进行跨进程通信,具体实现是通过进程间共享内存和进程间信号量来完成的。当客户端调用服务端的方法时,Binder会将客户端的请求封装成一个数据结构,然后通过驱动将数据发送给服务端。服务端接收到请求后,再将处理结果返回给客户端。
- Binder对象的引用计数:Binder对象的引用计数机制可以确保在没有客户端使用时,服务端可以被回收。当没有客户端使用时,Binder对象会调用其onLastStrongRef()方法,然后被销毁。
IPC 机制:进程间通信机制
Binder机制是Android系统中的一个重要的进程间通信(IPC)机制。以下是一些与Binder机制相关的面试知识点:
-
Binder的基本原理:Binder机制基于C/S架构,使用了驱动层、服务管理器、Binder驱动和Binder对象等组件来实现进程间通信。
-
Binder的角色:在Binder机制中,有三种主要角色:客户端、服务端和Binder驱动。客户端通过代理对象与服务端进行通信,而Binder驱动负责处理进程间的数据传输和通信。
-
Binder对象:在Binder机制中,进程间通信是通过Binder对象进行的。每个Binder对象都有一个唯一的标识符(Binder引用),用于在不同进程之间进行通信。
-
进程间通信的方式:Binder机制提供了多种进程间通信的方式,包括跨进程方法调用、跨进程数据传输和跨进程事件通知等。
-
AIDL(Android Interface Definition Language):AIDL是一种用于定义客户端和服务端之间接口的语言,它可以帮助开发者生成跨进程通信所需的代码。
-
进程间通信的安全性:Binder机制通过权限验证和用户ID(UID)来确保进程间通信的安全性,防止未授权的访问和恶意行为。
-
Binder的性能优化:在使用Binder机制时,可以通过减少跨进程调用次数、使用轻量级数据传输方式和优化服务端代码等方式来提高性能。
6、linux的共享内存有几次拷贝,为啥android不使用linux的IPC机制
Linux 中的共享内存在使用时通常涉及两次拷贝。首先,数据从用户空间被拷贝到内核空间,然后再从内核空间拷贝到另一个进程的用户空间。
Android 之所以不直接使用 Linux 的共享内存,是因为 Android 使用了基于 Binder 的进程间通信机制。Binder 通过将数据序列化为跨进程的消息进行传递,避免了额外的内核空间拷贝。这种设计可以提供更高效的进程间通信,并且具有更好的安全性和稳定性。
此外,Android 还提供了其他的共享内存机制,如 Ashmem(匿名共享内存),用于实现特定的共享内存需求,但它并不是 Android 应用程序常用的进程间通信方式。
四、启动流程
1、大体说下一个应用程序安装到手机上时发生了什么?
应用安装时,系统会先将 APK 复制到系统目录,校验签名合法性,解析AndroidManifest文件获取四大组件与权限,为应用创建独立数据目录与 UID,对 dex 进行 dex2oat 优化,最后将应用信息注册到 PackageManagerService 并生成桌面图标,完成安装。
1、dex2oat优化:
系统对 APK 里的 dex 文件做编译优化:
- 生成 oat 可执行文件
- 放入
/data/dalvik-cache/ - 让后续运行更快
安装慢,大多时间都耗在这里。
2、UID
它是 Android 系统给应用分配的 Linux 用户 ID ,用来做权限隔离、沙盒控制。
系统级应用分身 / 工作空间
比如微信双开:
- 原始微信:包名
com.tencent.mm,UID = 10123 - 分身微信:包名 仍然是
com.tencent.mm,UID = 10188
- 应用分身一定是新 UID 吗?
分两种:
① 系统双开(小米、华为、OPPO 双开)
- 系统级支持
- 新 UID、新数据目录、独立运行
- 安全、稳定,系统层面完全隔离
② 第三方双开 App(双开助手、平行空间等)
- 没有系统支持
- 共用同一个 UID
- 自己在内部做虚拟沙盒、虚拟组件环境
- 本质还是一个进程里跑多个逻辑应用,所以稳定性、权限都差一些
Android 权限管理的底层,就是 Linux 的 UID 用户权限机制,用于实现应用沙箱隔离;一个 Android 应用,在底层就是一个 Linux 用户(UID)。但是有2处特殊:
- 一个应用有多个进程,它们还是同一个UID
- 应用分身(系统双开)是 "同一个应用,多个用户"
上层再通过 PackageManagerService 扩展了相机、定位、存储等功能权限,最终所有权限检查都以 UID 为核心依据
2、进程启动顺序:
- Zygote fork
- ActivityThread.main()
- 初始化主线程 Looper
- attach 到 AMS
- 实例化 ContentProvider → 调用 onCreate
- Application 实例化 → attachBaseContext → onCreate
- 再启动 Activity/Service
3、Activity的冷启动流程
桌面 Launcher 发起启动请求 → 系统服务(AMS)处理
Zygote 孵化新 App 进程 → 主线程初始化 Application
AMS 调度启动目标 Activity → 主线程创建、渲染 Activity
页面可见,冷启动完成
4、Android系统启动流程是什么
1. 上电 & BootROM 启动
- 手机按下电源键,CPU 上电
- 执行固化在芯片里的 BootROM 代码
- 加载并校验 BootLoader
作用:最底层硬件初始化,引导系统启动。
2. BootLoader 阶段
- 初始化硬件(DDR、时钟、NAND/eMMC)
- 选择启动模式(正常 / Recovery / 刷机)
- 加载 Linux 内核(Kernel)到内存并启动
作用:系统引导程序,类似电脑的 BIOS。
3. Linux 内核启动
内核启动后做三件事:
- 挂载根文件系统
- 启动 0 号进程 idle
- 启动 1 号进程:init
这是 Android 世界的起点进程。
4. init 进程启动(Android 世界的祖宗)
init 是用户空间的第一个进程,核心工作:
-
解析 init.rc 脚本
-
创建文件系统、挂载分区
-
启动系统关键守护进程:
- servicemanager(Binder 管家)
- surfaceflinger(显示服务)
- vold(存储管理)
- zygote 进程(Android 所有应用的母进程)
关键点:
init → Zygote 是整个 Android 生态的入口。
5. Zygote 进程启动(最关键)
Zygote 是所有 App 进程的父进程,作用:
- 预加载系统资源、系统类、主题、资源文件
- 创建 SystemServer 进程(fork 自己)
- 开启 Socket 等待孵化新 App 进程
所有 App 进程都是 Zygote fork 出来的。
6. SystemServer 进程启动
SystemServer 是系统核心服务的容器,启动:
- 启动 AMS(ActivityManagerService)
- 启动 PMS(PackageManagerService)
- 启动 WMS、WindowManagerService
- 启动其他系统服务(电池、网络、蓝牙等)
AMS、PMS、WMS 都在这里诞生。
7. 启动桌面 Launcher
- AMS 准备就绪后
- 发送 Intent 启动 HOME 类别应用
- 系统桌面 Launcher 启动并显示
5、四大组件启动过程
Zygote读:[ˈzaɪɡoʊt]
AMS:ActivityManagerService
Activity 启动流程(最常考)
- App →
startActivity→ Binder 调用 AMS - AMS 校验权限、创建 / 查找
ActivityRecord - 目标进程未启动 → AMS 让 Zygote fork 进程
- 进程启动 → 初始化
ActivityThread - AMS 发送
SCHEDULE_LAUNCH_ACTIVITY事务 - App 主线程 Handler 处理 →
handleLaunchActivity - 创建 Activity → 调用
onCreate → onStart → onResume
Service 启动流程
- startService 流程
- App →
startService→ AMS - AMS 检查服务是否存在
- 进程未启动则 fork 进程
- 系统通过
ApplicationThread调用handleCreateService - 实例化 Service →
onCreate→onStartCommand
- bindService 流程
- 同上,先创建 Service
- 回调
onBind - 返回 Binder 给客户端,建立长连接
BroadcastReceiver 接收流程
- 发送广播 → AMS
- AMS 匹配所有静态 / 动态 Receiver
- 动态 Receiver:直接分发
- 静态 Receiver:进程未启动则 fork 进程
- 系统通过
handleReceiver回调onReceive - 运行在主线程,超时 ANR
ContentProvider 启动流程
- 进程启动时,AMS 通知
ActivityThread - 在
Application创建之前 - 系统自动实例化 ContentProvider
- 调用
attachInfo→onCreate - 之后才创建 Application