1. Android面试核心知识点解析
作为移动开发领域的主流平台,Android技术栈的深度和广度都在不断扩展。根据我参与近百场技术面试的经验,候选人常在这几个核心领域暴露出知识盲区:
1.1 四大组件深度剖析
Activity生命周期是基础中的基础,但90%的候选人无法完整描述从启动到销毁的全过程。特别容易忽略onSaveInstanceState()和onRestoreInstanceState()的调用时机,这两个方法在横竖屏切换时至关重要。建议手绘完整的生命周期流程图,标注每个回调方法触发时的系统状态。
Service的两种启动方式(startService和bindService)在实际项目中如何选择?这里有个经验法则:如果是后台独立任务(如下载文件),用startService;需要与Activity交互(如音乐播放控制),则用bindService。注意bindService默认不会调用onStartCommand(),这个细节经常被忽视。
1.2 多线程编程实战要点
HandlerThread与IntentService已经逐渐被更现代的协程替代,但理解其原理仍然必要。我曾遇到一个内存泄漏案例:在Activity中创建HandlerThread但未正确调用quit(),导致线程持续持有Activity引用。正确的做法是在onDestroy()中调用:
java复制handlerThread.quitSafely();
协程的取消机制是面试高频考点。很多开发者不知道协程的取消是协作式的,必须在协程体内定期检查isActive状态。比如网络请求时应该这样写:
kotlin复制withContext(Dispatchers.IO) {
if(!isActive) return@withContext
// 执行网络请求
}
1.3 性能优化进阶技巧
内存优化方面,LeakCanary只能检测Activity泄漏,对于其他对象需要使用Android Studio的Memory Profiler。有个实用技巧:在怀疑发生泄漏的页面操作后,手动触发GC(点击Profiler中的垃圾桶图标),然后导出hprof文件用MAT分析。
布局优化不止是ConstraintLayout。我在项目中发现,过度使用include标签反而会增加measure时间。正确的优化路径应该是:
- 先用Layout Inspector检查嵌套层级
- 使用
标签减少ViewGroup层级 - 对复杂ItemView开启硬件加速
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Framework层高频问题解析
2.1 Binder机制原理
Binder是Android面试的"必考题",但多数人只停留在"AIDL接口定义"层面。实际上,Binder驱动在内核层的实现才是精髓。建议重点理解:
- 内核中的binder_proc结构体如何维护进程映射
- 一次跨进程调用如何通过ioctl(BINDER_WRITE_READ)完成
- Parcel序列化时为什么要实现Parcelable接口
2.2 View事件分发机制
事件分发的"三剑客"(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)需要配合实际场景理解。我常问的题目是:在RecyclerView的Item中有个Button,点击时事件如何传递?正确答案是:
- Activity.dispatchTouchEvent
- RecyclerView.dispatchTouchEvent
- RecyclerView.onInterceptTouchEvent(返回false)
- Button.dispatchTouchEvent
- Button.onTouchEvent
2.3 WindowManager体系
Window的三种类型(应用Window、子Window、系统Window)在实际开发中的应用场景:
- Toast属于系统Window,所以不需要申请悬浮窗权限
- PopupWindow默认是子Window,必须依附于Activity
- 自定义悬浮窗需要TYPE_APPLICATION_OVERLAY权限(Android 8.0+)
3. 架构设计实战问题
3.1 MVVM与Jetpack组件
ViewModel的生命周期长于Activity是个双刃剑。我在项目中发现,如果ViewModel持有Repository引用,而Repository又持有Retrofit实例,在快速旋转屏幕时可能导致多个网络请求同时发出。解决方案是:
kotlin复制class MyViewModel : ViewModel() {
private val repository = Repository.getInstance()
// 使用LiveData合并重复请求
val data = repository.fetchData().cachedIn(viewModelScope)
}
3.2 依赖注入实践
Hilt比Dagger2更友好,但仍有学习曲线。常见错误是忘记添加@HiltAndroidApp到Application类,或者在非Activity/Fragment中使用@AndroidEntryPoint。建议建立标准的DI模块组织方式:
kotlin复制@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
4. 疑难问题排查思路
4.1 ANR分析实战
ANR日志不是简单的看main线程堆栈。我总结的分析步骤:
- 检查/data/anr/traces.txt获取完整信息
- 用systrace分析CPU调度情况
- 重点观察Binder调用阻塞(出现"Binder transaction")
- 检查是否在主线程执行IO或复杂计算
4.2 内存泄漏排查
除了LeakCanary,Android Studio的Memory Profiler可以捕获更复杂的泄漏链。关键技巧:
- 在怀疑泄漏的操作前后手动触发GC
- 按包名过滤,排除系统对象干扰
- 对比多个hprof文件,观察对象增长趋势
4.3 冷启动优化
启动时间优化不能只看Logcat的displayed时间。更准确的方法是:
bash复制adb shell am start -W -n com.example/.MainActivity
重点关注TotalTime和WaitTime的差值。常见的优化手段包括:
- 延迟初始化非关键组件
- 使用App Startup库统一管理初始化
- 避免在Application构造函数中执行耗时操作
