Java基础与集合框架
在2020年的Android面试中,Java基础依然是考察的重中之重。面试官不仅关注你是否知道API的用法,更关注你对底层原理的理解,特别是集合框架的源码实现和并发编程。
HashMap底层原理
HashMap是Android开发中使用频率最高的数据结构之一。在JDK1.7中,HashMap由数组+链表组成;而在JDK1.8中,引入了红黑树,当链表长度超过8且数组长度超过64时,链表会转换为红黑树,以提高查询效率。
⚡ 面试关键点
1. HashMap的扩容机制:默认初始容量16,负载因子0.75,扩容时容量翻倍。
2. Hash冲突解决:链地址法。
3. 为什么选择红黑树?因为红黑树查询时间复杂度为O(log n),而链表为O(n)。
并发编程与线程池
Android开发中离不开线程池的使用。面试官常问ThreadPoolExecutor的核心参数:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(空闲线程存活时间)、unit(时间单位)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略)。
// 示例:创建核心线程池
ExecutorService executor = new ThreadPoolExecutor(
5, // corePoolSize
10, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // workQueue
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy() // handler
);
Android核心组件与机制
Android四大组件(Activity, Service, BroadcastReceiver, ContentProvider)的生命周期及其启动流程是必考题。此外,Binder机制作为Android IPC的核心,也是区分初级和高级工程师的关键。
Activity启动流程
Activity的启动过程涉及AMS(Activity Manager Service)、ActivityStack、ApplicationThread等多个组件。整个过程是一个跨进程通信的过程。
Client进程发起请求
调用startActivity(),通过Instrumentation发起请求。
AMS处理
请求到达系统服务的AMS,AMS进行权限检查和进程管理。
创建新进程
如果需要启动新进程,AMS通知Zygote创建新进程。
回调Client
通过ApplicationThread回调到Client进程,执行onCreate(), onStart(), onResume()。
Binder机制简析
Binder是Android系统中一种进程间通信(IPC)机制。它基于C/S架构,分为Client、Server、ServiceManager和Binder驱动。Binder的优势在于一次内存拷贝,效率高,安全性好。
Handler消息机制深度解析
Handler、Looper、MessageQueue、Message构成了Android的消息机制。这是保证Android线程安全的核心,也是面试中极易被追问的难点。
核心组件关系
- Message:消息对象,包含what、arg1、arg2、obj等字段。
- MessageQueue:消息队列,采用单链表数据结构,负责消息的入队和出队。
- Looper:消息循环器,无限循环从MessageQueue中取消息,分发给Handler。
- Handler:消息发送和处理者,负责将消息放入MessageQueue,并处理返回的消息。
⚙️ 主线程Looper
Android主线程(ActivityThread)在启动时会创建Looper和MessageQueue,并进入loop()循环。如果主线程Looper退出,程序将崩溃。
⚙️ 死循环问题
Looper.loop()是死循环,为什么不会导致ANR?因为ANR是主线程长时间无响应,而Looper是事件驱动,只有在处理消息耗时过长时才会触发ANR。
⚙️ 消息轮询
当MessageQueue中没有消息时,Looper会阻塞在pollOnce(),直到有新消息到来,唤醒线程。
Android性能优化实战
性能优化是高级Android工程师的必备技能。2020年的面试中,面试官更关注具体的优化案例和数据支撑,而非空洞的理论。
内存泄漏排查与解决
内存泄漏会导致App OOM,严重影响用户体验。常见的内存泄漏场景包括:非静态内部类持有外部类引用、资源未关闭、单例模式滥用等。
| 泄漏场景 | 原因分析 | 解决方案 |
|---|---|---|
| Handler泄漏 | Handler为非静态内部类,持有Activity引用 | 使用静态内部类+WeakReference,或在onDestroy中removeCallbacks |
| 单例泄漏 | 单例持有Activity Context | 单例使用Application Context |
| 资源未关闭 | Cursor、Stream等未close | 使用try-with-resources或finally块关闭 |
| Bitmap过大 | 直接加载大图到内存 | 使用BitmapFactory.Options进行采样压缩 |
启动速度优化
冷启动优化主要从以下几个方面入手:
1. 减少Application初始化耗时。
2. 延迟初始化非关键组件。
3. 优化布局层级,使用ConstraintLayout或Merge标签。
4. 使用TraceView或Systrace定位耗时操作。
架构设计与Jetpack
2020年,MVVM架构成为主流,Jetpack组件库的普及使得架构搭建更加规范。面试官常问MVC、MVP、MVVM的区别,以及LiveData和ViewModel的原理。
MVVM vs MVP
MVP中Presenter需要持有View的引用,容易导致内存泄漏,且接口定义繁琐。MVVM通过DataBinding或LiveData实现View与Model的绑定,减少了Presenter的介入,代码更简洁。
Jetpack核心组件
- LiveData:可观察的数据存储器,遵循生命周期,避免内存泄漏。
- ViewModel:UI相关数据持有者,配置更改后数据不丢失。
- Room:SQLite对象映射库,简化数据库操作。
- Navigation:简化Fragment导航,支持Deep Link。
自定义View进阶
自定义View是Android开发的难点,也是面试中的加分项。主要考察Measure、Layout、Draw三个过程,以及事件分发机制。
事件分发机制
事件分发涉及三个方法:onInterceptTouchEvent(拦截)、dispatchTouchEvent(分发)、onTouchEvent(处理)。规则如下:
1. 事件从Activity的dispatchTouchEvent开始。
2. 如果ViewGroup拦截,则事件传递给onInterceptTouchEvent,再由onTouchEvent处理。
3. 如果不拦截,则传递给子View的dispatchTouchEvent。
⚡ 面试陷阱
为什么ScrollView嵌套ListView只显示一行?因为ScrollView和ListView都有滚动行为,冲突导致ListView无法获取正确的测量高度。解决方案:重写ListView的onMeasure方法,或计算总高度。
高频面试题Q&A
1. String、StringBuffer、StringBuilder的区别?
String是不可变的,每次修改都会创建新对象;StringBuffer和StringBuilder是可变的。StringBuffer是线程安全的(synchronized),StringBuilder是非线程安全的,性能更高。
2. 什么是反射?有什么优缺点?
反射可以在运行时获取类的信息并操作对象。优点是灵活,缺点是性能较低,且破坏封装性。
1. Android 10引入了哪些新特性?
分区存储(Scoped Storage)、暗色模式、5G支持、隐私权限变更等。
2. 如何优化RecyclerView?
固定大小(setHasFixedSize)、复用视图(getItemViewType)、预加载(setItemPrefetch)、减少notifyDataSetChanged的使用,改用DiffUtil。
1. 你如何学习新技术?
通过官方文档、GitHub源码、技术博客、社区论坛等多渠道学习,并结合项目实践验证。
2. 遇到技术难题如何解决?
首先分析日志和堆栈,定位问题;其次查阅官方文档和社区资源;最后必要时寻求同事帮助或重构代码。