Android 应用开发面试学习清单
共 7 个主题分组、64 篇内容
面向 中级(3-5 年)Android 应用开发岗 的系统复习资料。
你的背景画像:设备指纹 / 风控 SDK 开发者,强项 C/C++ 与 NDK/JNI、系统底层、逆向视角; 短板在 UI 层(View / Compose)、Kotlin 协程 / Flow、Jetpack 全家桶、应用架构。 副技能 iOS 基础。
本资料策略:重点补短板(★),把强项包装成差异化亮点(☆),iOS 作为跨端谈资(辅)。
如何使用这套资料
- 先读
00-面试路线与自我定位.md,想清楚怎么把“风控 SDK 背景“讲成应用岗的优势。 - 按下面“复习路线“的优先级顺序学,先攻短板(协程 → UI → Jetpack → 架构 → 测试体系)。
- 每篇结构统一:知识点讲解 → 高频面试题 + 参考答案要点 → 易错点 / 追问。
- 学完一个知识点,回到本页的“自测清单“打勾
- [x],追踪进度。
复习路线(按优先级)
| 阶段 | 重点 | 对应文档 |
|---|---|---|
| 第一优先(短板,必攻) | 协程 / Flow、View 体系、Compose、Jetpack、架构、测试体系、并发、深度扩展 | 02, 05, 06, 07, 08, 24, 33-39, 42, 49, 51 |
| 第二优先(高频,巩固) | Kotlin 核心及进阶、Java/JVM、四大组件、系统原理、性能、RxJava | 01, 03, 04, 09, 10, 27, 50 |
| 第三优先(亮点,包装) | NDK/JNI、主流第三方库、APM、推送/保活、音视频、跨端与动态化、SDK与调试 | 11, 12, 25, 26, 29, 43-44, 47, 53, 55 |
| 第四优先(加分,速览) | iOS 基础、KMP、项目经验与软技能、复盘与追问防御 | 13, 30, 14, 62-63 |
| AI 辅助开发(趋势话题) | Vibe Coding、Harness Engineering、AI Coding 工程化进阶 | 31, 32, 56 |
| 贯穿始终(每日刷题) | LeetCode Hot 100 算法清单与解析 | 15 |
| 算法补充(查漏补缺) | 排序/位运算/并查集/前缀和差分/设计题、业务算法场景 | 16, 60 |
| 算法亮点(差异化) | 海量数据处理(结合你的 SDK 背景) | 17 |
| 计算机基础(必考四大件) | 网络排障、设计模式、操作系统与数据库进阶 | 18, 19, 21, 57-59 |
| 安全亮点(核武器) | Android 安全与逆向、移动安全防护体系(你的本行) | 20, 54 |
| 工程化与设计(中高级) | Gradle构建与发布体系、鉴权订单隐私合规、性能工具、系统设计 | 22, 28, 23, 40-41, 45-46, 48, 52, 61 |
自测清单(学完打勾)
01 Kotlin 语言核心
- val/var、空安全(
?.?:!!)、平台类型 - 扩展函数 / 扩展属性的原理(静态分发)
- 高阶函数、Lambda、
inline/noinline/crossinline - 作用域函数 let/run/with/apply/also 区别
- data class / sealed class / object / 伴生对象
- 属性委托 by lazy / Delegates.observable / 自定义委托
- 泛型型变 in/out、reified
02 Kotlin 协程与 Flow ★
- suspend 原理:CPS 变换与状态机
- 结构化并发:CoroutineScope / Job / 父子关系
- Dispatchers(Main/IO/Default)与 withContext
- launch vs async、Deferred
- 取消机制(协作式)与异常传播
- CoroutineExceptionHandler / supervisorScope / SupervisorJob
- 冷流 Flow vs 热流;StateFlow vs SharedFlow
- flowOn / buffer / conflate / collectLatest
03 Java 与 JVM 基础
- HashMap 原理(扩容、红黑树、并发问题)、ConcurrentHashMap
- synchronized vs ReentrantLock、volatile、CAS、AQS
- 线程池 ThreadPoolExecutor 七参数与拒绝策略
- JMM 内存模型、happens-before
- JVM 内存区域、GC 算法与垃圾回收器
- 类加载机制、双亲委派
04 Android 四大组件与基础
- Activity 生命周期、启动模式、taskAffinity
- Fragment 生命周期与 commit/commitNow、懒加载
- Service(前台/绑定)、IntentService、JobScheduler/WorkManager
- BroadcastReceiver(静态/动态、有序、LocalBroadcast)
- ContentProvider 与跨进程数据共享
- Intent、序列化 Serializable vs Parcelable、Context 类型
05 UI 体系 - View 与自定义 View ★
- View 绘制三大流程 measure / layout / draw
- MeasureSpec 与 onMeasure、wrap_content 处理
- 事件分发 dispatch / intercept / onTouchEvent
- 滑动冲突(外部 / 内部拦截法)
- 自定义 View / ViewGroup、自定义属性
- invalidate vs requestLayout、硬件加速
- Window / DecorView / ViewRootImpl 关系
06 UI 体系 - Jetpack Compose ★
- 声明式 UI 思想、@Composable 原理
- 重组(Recomposition)与跳过、稳定性
- 状态:remember / mutableStateOf / state hoisting
- 副作用:LaunchedEffect / DisposableEffect / SideEffect / derivedStateOf
- CompositionLocal、Modifier 原理与顺序
- 三大阶段 Composition / Layout / Drawing
- 与 View 互操作、性能优化(key、lambda)
07 Jetpack 架构组件 ★
- ViewModel 原理、生命周期、SavedStateHandle
- Lifecycle / LifecycleObserver、LiveData 原理与粘性事件
- Room(实体 / DAO / 迁移 / 协程&Flow 支持)
- Navigation、Hilt 依赖注入(vs Dagger)
- DataStore(替代 SharedPreferences)、WorkManager、Paging3
08 应用架构 - MVVM 与 MVI ★
- MVC / MVP / MVVM / MVI 演进与对比
- 单向数据流、State / Intent / Effect
- 分层(data / domain / ui)、Repository 模式
- UseCase、依赖倒置、可测试性
09 Android 系统原理
- Handler / Looper / MessageQueue、同步屏障、IdleHandler
- Binder 机制(一次拷贝、mmap、驱动)
- AMS / 应用启动流程 / 进程创建(Zygote)
- 类加载与热修复 / 插件化原理
- 进程间通信方式对比
10 性能优化
- 启动优化(冷 / 热启动、Splash、延迟初始化)
- 内存泄漏(常见场景、LeakCanary 原理)、内存抖动
- 卡顿与掉帧、Choreographer、ANR 原理与定位
- 包体积优化(R8/ProGuard、资源、so)
- 布局优化、工具(Profiler / Perfetto / Systrace)
11 NDK 与 JNI ☆
- JNI 数据类型映射、签名规则
- 局部 / 全局 / 弱全局引用、引用表溢出
- JNIEnv vs JavaVM、线程 AttachCurrentThread
- 静态注册 vs 动态注册 RegisterNatives
- native 调用 Java、异常处理
- native crash 捕获(signal / breakpad)
- CMake / ABI / so 加载与裁剪、现代 C++(RAII / 智能指针)
12 主流第三方库
- OkHttp(拦截器链、连接池、缓存)
- Retrofit(动态代理、协程适配)
- Glide / Coil(三级缓存、生命周期绑定)
- Gson / Moshi / kotlinx.serialization
- EventBus / 依赖注入框架对比
13 iOS 基础速览(辅)
- Swift 基础、可选值、ARC 内存管理
- UIViewController 生命周期、UIKit vs SwiftUI
- GCD、与 Android 概念对照
14 项目经验与软技能
- STAR 法则讲项目
- 怎么把风控 SDK 项目讲成应用岗亮点
- 常见 HR / 反问环节
- 算法准备方向
33 Android 版本适配
- Android 版本演进中的行为变更与兼容策略
- targetSdkVersion 升级风险、灰度验证与回滚方案
- 权限、后台限制、通知、前台服务等高频适配点
34 存储体系与 Scoped Storage
- 内部 / 外部 / App 专属目录与 MediaStore 使用场景
- Scoped Storage 迁移路径、兼容开关与权限边界
- 大文件、缓存、数据库、日志文件的存储治理方案
35 图片加载与缓存
- 图片加载链路:请求、解码、变换、缓存、展示
- 内存缓存 / 磁盘缓存 / 网络缓存的命中与失效策略
- 大图、列表滑动、生命周期绑定与 OOM 防护
36 启动优化专项
- 冷启动 / 温启动 / 热启动指标与阶段拆解
- Application 初始化治理、懒加载与异步预热边界
- SplashScreen、Baseline Profile、启动链路监控与回归验证
37 内存优化与泄漏排查
- Android 内存模型、Java 堆 / Native 堆 / 图形内存差异
- 常见泄漏场景与 LeakCanary / MAT 分析路径
- 内存抖动、Bitmap、缓存上限与线上告警指标
38 ANR 与卡顿排查
- ANR 类型、触发阈值、traces 与主线程阻塞定位
- Choreographer、VSync、掉帧指标与 Perfetto 分析
- 锁竞争、IO、Binder 调用、布局过深等排查路径
39 Binder 与 IPC 深入
- Binder 通信模型、驱动、ServiceManager 与代理对象
- AIDL、Messenger、ContentProvider 等 IPC 方式对比
- 大数据传输、死亡监听、线程池与安全校验边界
40 Gradle 构建性能专题
- Gradle 生命周期、Task Graph、增量构建与缓存机制
- Configuration Cache、Build Cache、并行构建适用条件
- 构建耗时定位、插件治理与 CI 构建优化策略
41 CI/CD 与发布体系
- CI 流水线阶段:检查、测试、构建、签名、发布
- 灰度发布、渠道包、回滚与版本门禁设计
- 自动化质量门禁、制品管理与敏感信息保护
42 App 架构落地案例
- 分层架构在真实业务中的模块职责划分
- Repository、UseCase、ViewModel 与 UI State 协作链路
- 架构取舍、团队协作、可测试性与演进成本表达
43 插件化 / 热修复 / 动态化
- 插件化类加载、资源加载、组件代理基本原理
- 热修复方案对比、兼容风险与发布安全边界
- 动态化收益、性能成本、合规风险与降级策略
44 WebView 与 Hybrid
- WebView 生命周期、缓存、进程、性能与内存治理
- JSBridge 通信模型、线程切换与安全白名单校验
- Hybrid 页面加载优化、异常监控与降级兜底
45 登录鉴权与账号体系
- 登录态、Token、Refresh Token 与会话续期机制
- OAuth2 / 单点登录 / 设备绑定的核心流程与风险点
- 账号安全、风控拦截、退出登录与多端一致性处理
46 支付订单与状态机
- 订单状态流转、幂等、防重放与超时关闭机制
- 支付渠道回调、客户端轮询、服务端对账协作
- 异常订单、补偿任务、退款与状态机设计表达
47 埋点与数据采集 SDK
- 埋点模型、事件属性、会话、用户标识与采样策略
- 数据缓存、批量上报、重试、压缩与弱网治理
- 隐私合规、SDK 性能开销与线上质量监控
48 隐私合规与权限治理
- 权限申请时机、最小化原则与用户拒绝后的降级体验
- 隐私政策、数据采集清单、SDK 合规审计流程
- 敏感信息脱敏、加密、日志治理与跨境/第三方共享风险
49 多线程并发专题
- Java/Kotlin 并发原语、线程池、锁与协程调度对比
- 共享状态、可见性、竞态条件与死锁排查方法
- Android 主线程约束、后台任务调度与取消传播
50 Kotlin 进阶专题
- inline / reified / value class / sealed 类型的面试表达
- Kotlin 泛型、协变逆变、委托与 DSL 设计能力
- 协程状态机、Flow 操作符与性能陷阱的深入理解
51 Compose 深水区
- 重组跳过、稳定性、remember key 与状态提升
- Modifier、Layout、SubcomposeLayout、自定义绘制核心机制
- Compose 性能分析、列表优化与 View 互操作边界
52 性能工具专题
- Android Studio Profiler、Perfetto、Systrace 的适用场景
- Macrobenchmark、Baseline Profile 与启动/滚动性能验证
- 线上性能指标、采样策略、问题复现与闭环治理
53 NDK Native 调试与 Crash 定位
- tombstone、addr2line、符号表、so 映射与崩溃还原
- lldb / ndk-stack / breakpad 等 Native 调试工具链
- JNI 边界、线程、信号处理与线上 Native Crash 归因
54 移动安全防护体系
- 应用加固、反调试、完整性校验与风险分层思路
- 数据加密、密钥管理、通信安全与本地存储防护
- 设备指纹、风控 SDK、防刷防薅羊毛的应用岗表达
55 跨端技术对比
- Flutter、React Native、KMP、WebView Hybrid 的架构差异
- 性能、研发效率、生态、包体积与团队成本取舍
- 跨端落地中的平台能力、调试、发布与降级策略
56 AI Coding 工程化进阶
- Context Engineering、任务拆解与 AI 代码审查闭环
- MCP、工具调用、自动化验证与可追溯开发流程
- AI 生成代码的风险:幻觉、越权修改、测试缺口与治理
57 数据库进阶
- SQLite 索引、事务、WAL、锁与查询优化原则
- Room 迁移、缓存一致性、分页与离线数据同步
- 数据库排障:慢查询、损坏恢复、并发写入与监控
58 操作系统进阶
- 进程 / 线程 / 调度 / 内存管理与 Android 运行时关系
- 虚拟内存、mmap、文件 IO、Page Cache 与性能影响
- 锁、信号、系统调用、进程通信在移动端的应用场景
59 网络排障专项
- DNS、TCP/TLS、HTTP/2、QUIC 等链路问题定位
- OkHttp 日志、抓包、证书、代理与弱网复现方法
- 超时、重试、连接池、缓存、网关错误的排查流程
60 Android 业务算法场景
- LRU、滑动窗口、优先队列等算法在业务中的应用
- 推荐、搜索、去重、限流、风控规则的算法化表达
- 复杂度分析、边界条件与工程落地取舍说明
61 移动端系统设计题库
- 即时通信、Feed、推送、离线缓存等移动场景设计框架
- 客户端架构、数据同步、弱网容错与服务端协作边界
- 容量估算、性能指标、监控告警与灰度降级方案
62 项目复盘专题
- STAR / 背景目标行动结果结构化复盘项目
- 指标提升、故障处理、协作冲突与技术取舍表达
- 失败经验、重做方案、个人贡献边界与证据准备
63 简历追问防御清单
- 简历每个技术点准备原理、实践、指标与追问答案
- 区分亲自负责、参与协作、学习了解的边界表述
- 针对夸大风险、数据真实性、项目细节进行反问演练
00 面试路线与自我定位
这一篇不讲技术,讲策略。你不是普通的应届/转行选手,你是“底层强、应用层有空白“的特殊画像。打法和别人不一样。
一、你的优势与劣势盘点
优势(面试中要主动亮出来)
| 能力 | 普通应用开发者 | 你 |
|---|---|---|
| C/C++ / NDK / JNI | 大多不会或只会调用 | 能独立写 SDK |
| 系统底层 / so / 内存 | 模糊 | 熟悉 |
| 逆向 / 安全 / 对抗视角 | 几乎没有 | 是你的饭碗 |
| 性能极限优化意识 | 一般 | 强(SDK 对体积/性能敏感) |
这些是你的护城河。很多 App 团队正缺懂 native、懂性能、懂安全的人(音视频、IM、支付、出海 App 尤其需要)。
劣势(面试中会被重点拷问,必须补)
- UI 层:View 绘制流程、事件分发、自定义 View、Compose —— 应用岗的核心,你接触少。
- Kotlin 协程 / Flow:现代 Android 异步基石,你不熟。
- Jetpack 全家桶:ViewModel/Room/Navigation/Hilt/DataStore,应用开发日常。
- 应用架构:MVVM/MVI、单向数据流、分层 —— 中级必考。
- 主流业务库实战:Retrofit/Glide/OkHttp 的工程化用法。
二、转型叙事:怎么讲你的故事
面试官一定会问:“你之前做风控 SDK,为什么转应用开发?能行吗?” 准备好这套话术:
“我在风控 SDK 做的是 Android 最底层的部分——native 采集、对抗、性能与体积优化。这让我对系统机制(Binder、进程、内存、so 加载)有比一般应用开发者更深的理解。我想往上走,把这份底层功底用在完整的产品上。UI 和上层框架是我最近重点补的,我已经系统学了协程、Compose、Jetpack 和 MVVM 架构。”
关键三点:
- 不贬低过去:底层经验是稀缺的,要包装成“比别人更懂系统“。
- 承认短板但展示行动:“我已经系统学了 X、Y、Z”(配合本资料的学习成果)。
- 给团队一个理由:“我能补团队在 native / 性能 / 安全上的短板”。
三、目标岗位选型(扬长避短)
优先投这些方向,你的底层背景是加分项而非累赘。每个方向都按“为什么契合 → 面试会问什么 → 怎么包装经历 → 可能追问“准备:
- 音视频 / 直播 App
- 为什么契合:音视频链路常接触 FFmpeg、编解码、OpenGL/音频采集、native crash 与性能调优,你的 C++/NDK/JNI 经验能直接迁移。
- 面试会问:JNI 调用开销怎么控制?native 崩溃怎么定位?音视频卡顿如何拆解到采集、编码、网络、渲染各环节?
- 怎么包装:把风控 SDK 里的 native 模块讲成“在宿主 App 约束下做稳定、低开销、可回滚的 native 能力“,突出跨层调用、线程模型、so 体积和崩溃治理。
- 可能追问:如果没做过播放器,不要硬装;回答“音视频业务链路我需要补,但 native 性能、JNI 边界、crash 定位这些底层问题我能快速接住“。
- IM / 通讯
- 为什么契合:IM 重视连接稳定性、弱网、消息可靠性、离线/重连和端侧性能,很多问题不是纯 UI,而是协议与状态机。
- 面试会问:弱网下如何保证体验?长连接断线重连怎么设计?消息去重、ACK、重试和本地落库怎么取舍?
- 怎么包装:强调你做 SDK 时对宿主环境、网络/设备差异、异常采集和后台约束的敏感度,把它转成“端侧可靠性“语言。
- 可能追问:若被问到完整 IM 架构,先按“连接层 → 消息状态 → 本地缓存 → UI 同步 → 失败补偿“分层,不要一上来堆大规模服务端名词。
- 出海 App / 工具类
- 为什么契合:出海和工具类常受包体积、机型兼容、启动速度、隐私合规、多语言环境影响,SDK 背景天然关注“不能拖累宿主“。
- 面试会问:包体积怎么拆?so ABI 如何收敛?低端机启动/内存如何优化?兼容性问题怎么排查?
- 怎么包装:讲你如何在 SDK 约束里做延迟初始化、按需加载、ABI/符号裁剪、异常兜底;这些都能转化为 App 侧工程质量。
- 可能追问:遇到隐私/合规问题时,用“最小化采集、用户授权、可配置开关、日志脱敏“这类工程原则回答,不要编造具体合规项目。
- 支付 / 金融 App
- 为什么契合:支付金融对安全、风控、稳定性和审计非常敏感,你的对抗视角能帮助团队提前发现风险点。
- 面试会问:如何防 Hook/篡改/重放?敏感数据怎么保护?安全能力如何避免影响性能和用户体验?
- 怎么包装:把风控经验翻译成“安全风险识别 + 端侧防护 + 性能可控 + 可观测“;强调防御和工程治理,而不是炫攻击细节。
- 可能追问:被追具体安全方案时,保持防御视角,说清威胁模型、边界和误报成本;不要夸大成“完全防住“。
- 大厂基础架构 / 性能团队
- 为什么契合:基础架构和性能团队关注启动、APM、稳定性、包体积、native 质量和跨业务复用,与你的 SDK 工程经验最接近。
- 面试会问:启动耗时如何拆解?APM 指标怎么定义?native crash 符号化怎么做?一个优化如何灰度和回滚?
- 怎么包装:突出“做给多个宿主/业务使用“的 SDK 思维:接口稳定、兼容性、监控、降级、性能预算、发布质量。
- 可能追问:如果问到业务产品经验不足,回应“我更适合先从性能/稳定性/native 基建切入,同时补齐 UI 和业务架构“。
谨慎投:纯营销活动类、纯 UI 堆叠的业务岗 —— 这类岗位你的优势用不上,而短板暴露无遗。
四、典型面试流程与各轮重点
| 轮次 | 考察重点 | 典型问题 | 回答结构 | 易翻车点 |
|---|---|---|---|---|
| 一面(基础) | Kotlin、四大组件、UI、协程、集合并发 | “协程取消怎么生效?”“View 事件分发怎么走?”“Activity 重建怎么保状态?” | 先给一句结论,再按“机制 → 场景 → 易错点“三段答;不会展开源码时,至少说清生命周期/线程/状态边界 | 只会背概念、不敢承认 UI/Jetpack 短板;把底层强项当借口跳过基础题 |
| 二面(深入) | 架构、性能、原理、项目细节 | “一个页面你怎么分层?”“启动慢怎么定位?”“SDK 怎么不拖累宿主?” | 用“问题现象 → 指标拆解 → 定位工具 → 方案取舍 → 验证结果“讲;项目题用 STAR,结果处只填真实数据 | 讲项目只有职责没有决策;性能优化只说“异步/缓存“不讲指标和验证 |
| 三面(亮点) | 难题、系统设计、native、稳定性 | “native crash 怎么治理?”“设计一个端侧 APM/埋点 SDK”“安全能力如何灰度?” | 把主场拉到“NDK/JNI → 稳定性 → 性能预算 → 监控回滚“;系统设计按需求、约束、模块、数据流、失败处理讲 | 炫技过多,忽略业务约束;安全话题讲成攻击教程;承诺无法验证的效果 |
| HR 面 | 稳定性、薪资、转型动机 | “为什么转应用?”“短板怎么补?”“未来 2-3 年规划?” | 用第二节叙事:肯定过去价值,承认上层短板,展示学习行动和岗位匹配;薪资提前准备区间 | 抱怨前公司/旧方向;把转型说成逃离;用空话证明学习能力 |
每轮都要准备一个“桥接句“:我过去做的是底层 SDK,现在补的是应用层 API 和架构实践;底层经验能帮助我在性能、稳定性、安全问题上比普通应用开发者更快定位根因。 这句话不是万能答案,而是把话题从“你没做过完整 App“拉回“你能给团队补什么能力“。
五、两个月冲刺计划(参考)
- 第 1-2 周:Kotlin 核心 + 协程/Flow(02 篇,最薄弱,先攻)。
- 第 3-4 周:UI 体系 View + Compose(05、06 篇)。
- 第 5 周:Jetpack + 架构(07、08 篇)。
- 第 6 周:系统原理 + 性能优化(09、10 篇)。
- 第 7 周:复习强项 NDK/JNI 做亮点(11),刷主流库(12)。
- 第 8 周:项目复盘(14)、算法、模拟面试、iOS 速览(13)。
六、心态提醒
你不是从零开始。底层功底是很多面试官给不出、也很羡慕的硬实力。你要补的是“上层广度“,这是可以在两个月内系统补齐的知识型短板,而不是需要多年积累的经验型短板。把姿态放在“我是带着系统功底来做应用“的位置,而不是“我是个 UI 新手“。
01 Kotlin 语言核心
Kotlin 是现代 Android 的第一语言。你会用,但要把“会用“升级到“讲得清原理“。本篇覆盖中级面试高频语法点的底层机制。
一、空安全(Null Safety)
Kotlin 把 null 检查提前到编译期。
val a: String不可空;val b: String?可空。- 安全调用
b?.length:b 为 null 时整体返回 null。 - Elvis
b?.length ?: 0:为 null 时给默认值。 - 非空断言
b!!:为 null 时抛 NPE(慎用)。 - 平台类型
String!:来自 Java 的类型,Kotlin 不知其可空性,调用方负责。
易错:lateinit var 用于非空且延迟初始化(只能用于 var、非基本类型),访问前未初始化抛 UninitializedPropertyAccessException,可用 ::x.isInitialized 判断。by lazy 用于 val,线程安全延迟初始化。
二、扩展函数 / 扩展属性
fun String.lastChar(): Char = this[length - 1]
原理(高频追问):扩展函数编译成静态方法,接收者作为第一个参数传入。所以:
- 扩展函数是静态分发,不是多态——调用哪个由声明类型决定,不是运行时类型。
- 不能真正修改类、不能访问 private 成员。
- 扩展属性没有 backing field,只能定义 get/set。
三、高阶函数与 inline
inline fun <T> measure(block: () -> T): T { ... }
- Lambda 默认会被编译成
Function对象,有对象创建开销。 inline把函数体和 lambda 直接内联到调用处,消除对象分配,还能让 lambda 内的return直接返回外层函数(非局部返回)。noinline:某个 lambda 参数不内联。crossinline:禁止该 lambda 非局部返回(用于会在别处调用的场景)。reified:配合 inline,让泛型类型在运行时可见(T::class),解决泛型擦除。- 边界:
reified只让内联函数调用点能拿到T的运行时类型,不能恢复集合元素的完整泛型实参;例如仍无法把List<String>和List<Int>的元素类型当作普通运行时类型安全区分。
四、作用域函数(let/run/with/apply/also)
| 函数 | 引用对象 | 返回值 | 典型用途 |
|---|---|---|---|
let | it | lambda 结果 | 非空判断后操作 x?.let { } |
run | this | lambda 结果 | 配置对象并计算结果 |
with | this | lambda 结果 | 对一个对象多次操作(非扩展) |
apply | this | 对象本身 | 初始化配置 Paint().apply { } |
also | it | 对象本身 | 副作用(打日志)不改链式 |
记忆法:返回结果用 let/run/with,返回自身用 apply/also;用 it 是 let/also,用 this 是 run/with/apply。
五、class 家族
- data class:自动生成 equals/hashCode/toString/copy/componentN。注意 copy 是浅拷贝;只有主构造参数参与生成。
- sealed class / sealed interface:密封类型,子类受限在同一模块。配合
when可穷尽分支(无需 else),适合表达状态(Loading/Success/Error)。 - object:单例;
companion object伴生对象(类级别成员,可实现接口、可命名)。 - enum:枚举,可带属性和方法。
- 嵌套 vs 内部类:Kotlin 嵌套类默认是静态的;加
inner才持有外部类引用。
六、委托(Delegation)
- 类委托:
class B(b: Base) : Base by b,把接口实现委托给成员,组合优于继承。 - 属性委托:
by lazy { }:首次访问时计算,默认SYNCHRONIZED线程安全。Delegates.observable:值变化时回调。Delegates.notNull():非空但延迟赋值。by map:从 Map 读取属性。- 自定义委托需实现
getValue/setValue。
七、泛型型变
- out T(协变):只能作为输出(生产者),
List<out T>,List<String>可赋给List<Any>。 - in T(逆变):只能作为输入(消费者),
Comparator<in T>。 *星投影:不关心具体类型时使用。- PECS:Producer-Extends(out),Consumer-Super(in)。面试可用一句话落地:只从容器里读
T用out,只往容器里写T用in;既要读又要写具体T时通常不要加型变,否则编译器会限制不安全操作。
高频面试题
Q1:== 和 === 的区别?
== 比较值(调用 equals),=== 比较引用。Java 的 == 对应 Kotlin 的 ===。
Q2:lateinit 和 by lazy的区别?
lateinit 用于 var、非空、可多次赋值、不能用于基本类型、由开发者负责初始化时机;lazy 用于 val、首次访问自动初始化、线程安全可配置。
Q3:扩展函数能被重写吗?为什么? 不能。扩展函数是静态分发,编译成静态方法,调用哪个由声明类型决定而非运行时类型,所以没有多态。
Q4:inline 一定能提升性能吗? 不一定。inline 消除 lambda 对象分配,适合高阶函数;但内联会增大字节码,对大函数滥用反而增加体积、降低性能。Kotlin 编译器会对大 inline 函数告警。
Q5:Kotlin 的 Unit、Nothing、Any 区别?
Any 是所有非空类型的根(类比 Object);Unit 表示无返回值(类比 void,但是真实对象);Nothing 表示永不返回(抛异常或死循环),是所有类型的子类型。
Q6:data class 用作 HashMap 的 key 安全吗? 安全(自动生成了 hashCode/equals),但若字段可变,作为 key 后修改字段会导致查找失败 —— 应保证 key 不可变。
Kotlin 协程与 Flow
Java 与 JVM 基础
Kotlin Multiplatform
Kotlin 进阶专题
四大组件与基础
UI 体系 - View 与自定义 View
UI 体系 - Jetpack Compose
Jetpack 架构组件
应用架构 - MVVM 与 MVI
Android 系统原理
性能优化
测试体系
Android 版本适配
存储体系与 Scoped Storage
图片加载与缓存
启动优化专项
内存优化与泄漏排查
ANR 与卡顿排查
Binder 与 IPC 深入
App 架构落地案例
多线程并发专题
Compose 深水区
NDK 与 JNI
主流第三方库
iOS 基础速览
项目经验与软技能
25 APM 与线上监控
☆ APM 是把“性能优化“从本地经验升级成线上体系的关键。你的风控 SDK 背景可以重点讲 native crash、采样、灰度和宿主影响控制。
一、APM 监控什么
| 类型 | 指标 | 关键证据 |
|---|---|---|
| Crash | Java crash、native crash、崩溃率 | 堆栈、版本、机型、ABI |
| ANR | 主线程阻塞、输入超时、广播/Service 超时 | traces、主线程栈、锁等待 |
| 卡顿 | 慢帧、冻结帧、帧率 | Choreographer/FrameMetrics/Perfetto |
| 启动 | 冷启动、首帧、可交互时间 | launch trace、业务埋点 |
| 网络 | 成功率、耗时、错误码、弱网 | interceptor、DNS/TLS/connect/read 分段 |
二、Crash 监控:Java 与 Native
Java crash 常通过 Thread.setDefaultUncaughtExceptionHandler 捕获;native crash 需要 signal handler 或 Breakpad/Crashpad 这类方案。
面试边界:不要说“所有 native crash 都能优雅恢复“。多数情况下只能采集现场、下次启动上报、灰度回滚。
三、ANR 与卡顿监控
- ANR:系统判定,重点是拿到 traces 和主线程阻塞证据。
- 卡顿:应用侧可用主线程 watchdog、Choreographer 帧回调、FrameMetrics 监控。
- 线上采样必须控制开销,避免监控本身制造卡顿。
四、启动与网络监控
启动监控要区分进程创建、Application、首 Activity、首帧、业务首页可交互。网络监控要拆 DNS、TCP、TLS、请求、响应、解析,不要只报一个总耗时。
五、上报链路、采样与隐私
- 本地缓存:避免 crash 当场丢失日志。
- 批量上报:减少电量和流量开销。
- 采样:高频事件不能全量。
- 隐私:不上传明文 token、手机号、身份证、设备敏感字段。
六、怎么把 SDK 经历讲成亮点
可以这样组织:“SDK 嵌入宿主 App 后,我关注的不只是功能成功,还要保证不拖累宿主稳定性。我们会监控 native crash、初始化耗时、线程/网络开销,灰度阶段看指标,异常时能按版本/ABI/机型聚合定位。”
高频面试题
Q1:线上卡顿怎么监控? 答:轻量方案是主线程 watchdog 或 Choreographer 统计慢帧;深入定位要结合 Perfetto/trace。线上只采样关键指标,本地复现再做完整 trace。
Q2:native crash 怎么定位? 答:采集 signal、寄存器、线程栈、so build id/版本/ABI,结合未 strip 符号或 symbol server 还原堆栈,按版本和机型聚类。
Q3:APM SDK 会不会影响性能? 答:会,所以要采样、异步、批量、延迟上报,关键路径不做重 IO,监控逻辑本身也要被监控。
易错点 / 追问
- 不要把本地 Profiler 等同于线上 APM。
- 不要上传敏感业务数据。
- 不要只讲采集,还要讲聚合、告警、灰度回滚和修复闭环。