Android 面试知识点整理
-
- 一、四大组件(必问)
-
- [1.1 Activity](#1.1 Activity)
- [1.2 启动模式(launchMode)](#1.2 启动模式(launchMode))
- [1.3 Service](#1.3 Service)
- [1.4 BroadcastReceiver](#1.4 BroadcastReceiver)
- [1.5 ContentProvider](#1.5 ContentProvider)
- 二、Fragment
- [三、Handler 消息机制(必考)](#三、Handler 消息机制(必考))
- 四、存储
- 五、网络
- 六、异步与线程
- 七、内存优化
-
- [7.1 内存泄漏常见](#7.1 内存泄漏常见)
- [7.2 OOM 与 Bitmap](#7.2 OOM 与 Bitmap)
- 八、性能优化
- 九、Jetpack(官方架构组件)
- 十、Kotlin(加分/主流)
- 十一、适配与权限
- 十二、易踩坑清单
- [十三、高频面试题 25 连击](#十三、高频面试题 25 连击)
定位:Android 开发岗面试速通。
配套:《Java面试知识点梳理》(语言基础复用)+ 本文(平台/组件/优化)。
用法:每个模块先看"核心结论",再看"面试题",最后对照"易踩坑"。
一、四大组件(必问)
1.1 Activity
- 生命周期 :
onCreate(创建)→onStart(可见)→onResume(可交互)→onPause(失去焦点)→onStop(不可见)→onRestart→onDestroy(销毁)。 - 典型场景 :
- 启动 A:
onCreate→onStart→onResume - A 跳 B(标准):
A.onPause → B.onCreate→onStart→onResume → A.onStop - 按返回:
B.onPause → A.onRestart→onStart→onResume → B.onStop→onDestroy - 横竖屏切换:
onPause→onStop→onDestroy→onCreate→onStart→onResume(除非配置configChanges)。
- 启动 A:
1.2 启动模式(launchMode)
| 模式 | 行为 |
|---|---|
| standard | 每次新建实例,可多个 |
| singleTop | 栈顶复用(不新建),onNewIntent 接收 |
| singleTask | 栈内唯一,清除其上所有 Activity |
| singleInstance | 独占一个任务栈 |
1.3 Service
- 生命周期 :
onCreate→onStartCommand→onDestroy;startService独立运行,bindService绑定随调用者销毁。 - 前台服务 :Android 8+ 必须
startForeground(带通知),否则崩溃。 - IntentService (已废弃):内部单线程 HandlerThread,任务完成自动停止;新项目用 WorkManager / 协程。
1.4 BroadcastReceiver
- 标准广播(并行)/ 有序广播(
setPriority,可拦截)/ 本地广播(LocalBroadcastManager,更安全高效)。 - 注册:静态(Manifest,Android 8+ 大部分隐式广播受限)/ 动态(registerReceiver,需 unregister 防泄漏)。
1.5 ContentProvider
- 跨进程数据共享标准组件(通讯录、相册);底层 Binder;
query/insert/update/delete。
二、Fragment
- 生命周期 :
onAttach→onCreate→onCreateView→onActivityCreated→onStart→onResume→onPause→onStop→onDestroyView→onDestroy→onDetach。 - 与 Activity 通信 :接口回调 /
ViewModel共享 / 第三方 EventBus(谨慎)。 - 懒加载 :ViewPager2 +
FragmentStateAdapter;用onResume+ 标志位或setMaxLifecycle控制加载时机。 - add/hide vs replace :
add+show/hide保留实例、replace每次重建;事务需commitAllowingStateLoss防状态丢失异常。
三、Handler 消息机制(必考)
- 四件套 :
Handler(发/处理)、Looper(循环)、MessageQueue(队列)、Message(消息)。 - 主线程
Looper由ActivityThread.main()中Looper.prepareMainLooper()初始化,子线程需手动prepare+loop。 - 流程 :
sendMessage→ 入队 →Looper.loop()取消息 →dispatchMessage→handleMessage。 - 内存泄漏 :非静态内部类 Handler 持有 Activity 引用 → 消息未处理时 Activity 无法回收。解决:静态内部类 + 弱引用,或
onDestroy中removeCallbacksAndMessages(null)。
四、存储
| 方式 | 适用 | 注意 |
|---|---|---|
| SharedPreferences | 轻量键值(设项/登录态) | apply 异步(可能丢)、commit 同步;跨进程不可靠 |
| 内部文件 | 私有数据 | openFileOutput |
| 外部存储 | 大文件/共享 | 需运行时权限(Android 6+)+ 分区存储(Scoped Storage,Android 10+) |
| SQLite | 结构化数据 | 推荐 Room(编译期校验、LiveData 支持) |
| ContentProvider | 跨应用 | 标准接口 |
五、网络
- OkHttp:拦截器链(应用拦截器 / 网络拦截器)、连接池复用、缓存、WebSocket。
- Retrofit :动态代理 + 注解(
@GET/@POST/@Query/@Body)生成请求,配合 RxJava/协程suspend。 - 安全 :HTTPS(证书锁定
CertificatePinner)、敏感数据加密、防抓包。
六、异步与线程
| 方案 | 说明 |
|---|---|
| AsyncTask | 已废弃(内存泄漏/版本兼容问题) |
| HandlerThread | 自带 Looper 的子线程 |
| 线程池 | Executors 有风险,用 ThreadPoolExecutor |
| RxJava | 响应式流,线程切换 subscribeOn/observeOn |
| Kotlin 协程 | 轻量、结构化并发、suspend + 调度器(Dispatchers.IO/Main) |
七、内存优化
7.1 内存泄漏常见
- 静态变量持有 Activity / Context。
- 非静态内部类(Handler、Thread、AsyncTask)。
- 未注销监听(EventBus、广播、Sensor)。
- 资源未关闭(Cursor、Stream、Bitmap)。
- 工具:LeakCanary 自动检测。
7.2 OOM 与 Bitmap
Bitmap是大头:inSampleSize采样压缩、inBitmap复用、放res合适密度、及时recycle(Android 8+ 由 GC 管理)。- 图片库:Glide / Coil(自动内存+磁盘缓存、生命周期感知)。
八、性能优化
- 启动优化:冷/温/热启动;Application/Activity 中避免耗时(I/O、初始化);异步初始化(启动器/协程)、延迟加载、IdleHandler。
- 布局优化 :减少层级(ConstraintLayout)、
<include>/<merge>/<ViewStub>、避免过度绘制(开发者选项检测)。 - 卡顿 :主线程不要做 IO/复杂计算;Choreographer / Profiler 定位掉帧;
StrictMode抓主线程违规。 - 包体积:资源混淆(AndResGuard)、so 按架构分包、无用资源移除(R8/ shrinkResources)。
九、Jetpack(官方架构组件)
| 组件 | 作用 |
|---|---|
| ViewModel | 配置变更(旋屏)数据不丢,不持有 View |
| LiveData | 生命周期感知的可观察数据 |
| Room | 官方 ORM |
| WorkManager | 可靠的后台任务(替代 JobScheduler/IntentService) |
| Navigation | 统一导航、深链 |
| ViewBinding/DataBinding | 空安全视图绑定 / 数据绑定 |
| Lifecycle | 生命周期感知基类 |
MVVM 推荐架构:UI(Activity/Fragment)→ ViewModel → Repository → 数据源(网络/DB)。
十、Kotlin(加分/主流)
- 空安全 :
?可空、!!强转(慎用)、?:elvis、?.安全调用。 - 协程 :
suspend挂起、CoroutineScope+Job、Dispatchers切换线程、结构化并发(父取消子随之取消)。 - 语法糖 :扩展函数、
高阶函数/lambda、数据类data class、密封类sealed class、解构、默认参数。 - 协程 vs RxJava:协程更轻、结构化、可读性好;RxJava 操作符更全、老项目存量大。
十一、适配与权限
- 屏幕 :dp/sp 自适应;ConstraintLayout 百分比;刘海/挖孔(
DisplayCutout);折叠屏多窗口。 - 权限 :Android 6+ 运行时权限(
checkSelfPermission/requestPermissions);Android 10+ 分区存储;Android 12+ 精确位置分粗/细。
十二、易踩坑清单
| 坑 | 现象 | 解决 |
|---|---|---|
| Handler 内存泄漏 | Activity 不回收 | 静态类 + 弱引用 / 移除消息 |
| 静态 Context/View | 泄漏 | 用 Application Context |
| 主线程网络/IO | ANR | 切子线程 / 协程 |
| 广播未注销 | 泄漏/崩溃 | onDestroy unregister |
| 横竖屏重建丢数据 | 状态丢失 | ViewModel / onSaveInstanceState |
| SharedPreferences 跨进程 | 数据不准 | 用 ContentProvider/MMKV |
| 图片 OOM | 崩溃 | Glide + 采样 |
| 匿名内存 | 卡顿 | 懒加载 / 异步 |
十三、高频面试题 25 连击
- Activity 完整生命周期?
- A 跳 B 生命周期调用顺序?
- 四种启动模式区别?
- onSaveInstanceState 何时调用?
- Service 与 IntentService 区别?
- 前台服务为什么必须通知?
- 广播静态注册限制(Android 8+)?
- Handler 原理?子线程能用吗?
- 为什么 Handler 会内存泄漏?
- Looper.loop 为什么不会阻塞主线程?
- 简述 MessageQueue 的阻塞(epoll)?
- SharedPreferences 的 apply 与 commit 区别?
- 内部存储与外部存储区别?
- 分区存储是什么?
- OkHttp 拦截器有几种?区别?
- Retrofit 原理?
- 为什么 AsyncTask 被废弃?
- 协程相比线程优势?
- 常见内存泄漏场景?
- LeakCanary 原理?
- Bitmap 如何防止 OOM?
- 启动优化手段?
- 布局过度绘制如何排查?
- ViewModel 为什么不会被重建销毁?
- Kotlin 空安全怎么实现?