Android 中高级开发核心面试题与解析
前言
本文整理了 Android 中高级开发岗位的高频面试题,涵盖 Java 基础、Android 核心机制、系统框架、性能优化及音视频算法等方向。内容基于实际面试经验总结,旨在帮助开发者系统复习技术栈,提升面试通过率。
一、Android 核心机制
1. Activity 的启动方式
Activity 的 LaunchMode 决定了实例在任务栈中的行为:
- standard:默认模式。每次启动都创建新实例,不管栈中是否已存在。
- singleTop:如果目标 Activity 位于栈顶,则复用该实例并调用
onNewIntent;否则创建新实例。
- singleTask:栈内复用。若栈中存在该实例,则将该实例之上的所有 Activity 出栈,并调用
onNewIntent。同时具有 clearTop 机制。
- singleInstance:独占一个任务栈。该 Activity 是栈中唯一的实例,其他应用可通过 Intent 共享此全局唯一实例。
2. Handler 防止内存泄漏
Handler 导致内存泄漏的原因在于其内部持有 Looper 和 MessageQueue,且非静态匿名类会隐式持有外部 Activity 引用。
解决方案:
- 将 Handler 声明为静态内部类。
- 使用 WeakReference 持有 Activity 引用。
- 在 Activity 销毁时移除回调和消息。
public class MyActivity extends AppCompatActivity {
private static class MyHandler extends Handler {
private final WeakReference<MyActivity> mActivityRef;
public MyHandler(MyActivity activity) {
mActivityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MyActivity activity = mActivityRef.get();
if (activity != null) {
}
}
}
private MyHandler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new MyHandler(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
}
}
3. SoftReference 与 WeakReference 的区别
- WeakReference:弱引用对象的生命周期与强引用一致,只要 GC 发生时,无论内存是否充足,都会被回收。常用于缓存场景。
- SoftReference:软引用。仅在内存不足(OOM)时才进行回收。常用于实现内存敏感的缓存。
4. 如何避免 OOM
- 减少内存占用:使用 ArrayMap/SparseArray 代替 HashMap/ArrayList(针对小数据量)。
- 避免 Enum:在 Android 中 Enum 会消耗较多内存,尽量用 int 常量替代。
- Bitmap 优化:降低图片分辨率,使用
inSampleSize 采样加载,及时 recycle 不可复用的 Bitmap。
- 资源管理:避免加载过大的图片资源,考虑分段加载或懒加载。
5. Dalvik 进程、Linux 进程、线程的区别
- Dalvik/ART 进程:每个 Android App 运行在一个独立的虚拟机进程中,拥有独立的内存空间。
- Linux 进程:Dalvik 进程本质上是 Linux 进程,受内核调度。
- 线程:App 内的多个线程共享同一进程的内存空间,通过 IPC 或 Binder 通信。
6. Framework 工作原理及 View 生成机制
Framework 是对 Linux Kernel 和 Lib 库的封装,提供 WMS、AMS、Binder 等机制供 App 使用。
View 生成流程:
- attach:Activity 初始化时创建 PhoneWindow(Window 子类)。
- setContentView:在 onCreate 中调用,创建 DecorView。
- addView:DecorView 将布局文件加载进来,构建 View 树。
- 绘制:经过 Measure、Layout、Draw 三个阶段渲染到屏幕。
二、Java 基础与并发
1. Java 集合框架
- HashMap:基于数组 + 链表 + 红黑树。JDK 1.8 后解决哈希冲突采用链地址法,链表长度超过 8 转为红黑树。
- ConcurrentHashMap:JDK 1.7 分段锁,JDK 1.8 CAS + synchronized 保证线程安全。
- ArrayList vs LinkedList:ArrayList 基于动态数组,查询快插入慢;LinkedList 基于双向链表,插入删除快查询慢。
2. 多线程与线程池
- ThreadLocal:线程隔离变量,需手动 remove 防止内存泄漏。
- 线程池参数:corePoolSize, maximumPoolSize, keepAliveTime, workQueue, threadFactory, handler。
- 拒绝策略:AbortPolicy(抛异常)、CallerRunsPolicy(调用者执行)、DiscardPolicy(丢弃)等。
3. JVM 与 ART
- JVM:Java 虚拟机规范,不同厂商实现不同。
- ART:Android Runtime,取代了 Dalvik。采用 AOT(Ahead-Of-Time)编译,安装时预编译,运行时效率高但安装慢。
- GC 算法:标记 - 清除、复制、标记 - 整理、分代收集。
三、Android 性能调优
1. 启动优化
- 异步初始化:延迟非必要组件初始化。
- 主线程瘦身:减少主线程耗时操作,如 IO、网络、复杂计算。
- 冷启动指标:从点击图标到首帧绘制完成的时间。
2. 内存优化
- LeakCanary:检测内存泄漏工具。
- MAT:Memory Analyzer Tool,分析 Dump 文件。
- 监控:使用 System.out.print 或 Logcat 监控堆内存变化。
3. 卡顿检测
- Choreographer:监听 VSYNC 信号,判断帧绘制时间是否超过 16ms。
- StrictMode:检测主线程违规操作。
四、系统框架与 IPC
1. Binder 机制
- 特点:一次拷贝,支持跨进程通信,权限控制严格。
- 架构:Client -> Service Manager -> Server。
- 原理:Mmap 映射驱动,共享内存传输数据。
2. AMS/WMS
- AMS (ActivityManagerService):管理 Activity、Service、Broadcast 生命周期。
- WMS (WindowManagerService):管理窗口显示、输入事件分发。
3. 四大组件通信
- Intent:显式与隐式 Intent。
- ContentProvider:跨应用数据共享。
- BroadcastReceiver:广播接收,有序/无序广播。
五、音视频与 Flutter
1. 音视频基础
- 编码原理:去除冗余信息(空间/时间冗余),压缩率取决于编码格式(H.264/H.265)。
- 直播秒开:CDN 加速、预加载、降低首屏复杂度。
- 图像滤波:高斯模糊、均值滤波、中值滤波。
2. Flutter 高频点
- Widget 树:UI 描述层,不可变。
- Element 树:状态管理层,可复用。
- RenderObject 树:布局与绘制层,负责具体渲染。
- Dart 语言:AOT 编译,Hot Reload 热重载机制。
六、算法与数据结构
1. 常见算法
- 素数查找:埃拉托斯特尼筛法。
- 二分查找:适用于有序数组,时间复杂度 O(log n)。
- 最长回文子串:中心扩展法或 Manacher 算法。
- 雨水问题:双指针或动态规划计算接水量。
2. 数据结构
- 数组:连续内存,随机访问快。
- 链表:非连续内存,插入删除快。
- 树与图:层级关系与网状关系存储。
七、企业实战问题
- SP 频繁操作后果:可能导致数据库锁竞争,建议批量写入或使用内存缓存。
- SP 存储限制:通常几 MB,不适合存大文件。
- Application 启动 Activity:Context 需要 ContextWrapper 或 ContextThemeWrapper,不能直接用 Application 启动有主题要求的 Activity。
- SD 卡:Android 6.0+ 对外部存储权限管理更严格,建议使用 Scoped Storage。
结语
掌握上述知识点有助于应对 Android 中高级岗位的面试挑战。建议结合源码阅读与实际项目经验,深入理解底层原理,提升解决复杂问题的能力。