上篇聊完初级基础,这篇进入滴滴中级面经。中级岗要求能选型架构、用好Jetpack组件。MVP/MVVM架构对比、Dagger2依赖注入、Room数据库、WorkManager后台任务。
今天8道题覆盖滴滴中级面试核心考点。
Q1:MVP和MVVM有什么区别?
MVP(Model-View-Presenter):View只负责UI,Presenter处理业务逻辑,Model提供数据。通过接口通信。优点:逻辑和UI分离,可测试。缺点:接口爆炸(每个页面一套Contract)、Presenter持有View引用可能泄漏。
MVVM(Model-View-ViewModel):View观察ViewModel数据(LiveData/StateFlow),ViewModel不持有View引用。数据驱动UI——ViewModel数据变化自动更新View。优点:生命周期安全、代码简洁、支持ViewBinding。缺点:调试困难(数据流向不直观)。
选择:新项目推荐MVVM(Jetpack官方推荐),配合ViewModel+LiveData/Flow+Repository。
追问:MVI呢?MVI(Model-View-Intent)是单向数据流架构——View发送Intent(用户操作)→ Model处理 → 输出新State → View渲染。状态不可变、流向单一、可预测。配合Compose特别合适。
Q2:Dagger2的依赖注入原理是什么?
核心概念:@Inject标记构造函数或字段。@Module提供依赖实例(@Provides方法)。@Component连接Module和注入目标(编译时生成代码)。@Scope控制生命周期(@Singleton全局单例)。
编译时生成:Dagger2在编译期生成Java代码(不是反射),性能等同于手写new。DaggerAppComponent实现Component接口,内部包含Module的@Provides调用链。
依赖链:A依赖B,B依赖C。Dagger2自动解析——创建C → 用C创建B → 用B创建A。循环依赖在编译时报错。
追问:Dagger2和Hilt区别?Hilt是Google在Dagger2基础上封装的Android专用DI框架。Hilt自动管理Application/Activity/Fragment等Android组件的Component生命周期,减少样板代码。新项目推荐Hilt。
Q3:Room数据库怎么用?和SQLite有什么关系?
Room:SQLite的抽象层(ORM)。编译时验证SQL(拼错在编译时报错)、自动生成Dao实现、支持LiveData/Flow观察数据变化、支持迁移(Migration)。
核心组件:@Entity(数据类→表)、@Dao(数据访问接口→CRUD方法)、@Database(数据库类→持有Entity和Dao)。
查询方式:@Query("SELECT * FROM users WHERE age > :minAge")编译时验证。返回类型支持List<User>、LiveData<List<User>>、Flow<List<User>>。LiveData/Flow类型自动在数据变化时通知观察者。
迁移:版本升级时写Migration,Room执行迁移SQL。没写Migration会崩溃(或fallbackToDestructiveMigration删除重建)。
追问:Room性能优化?批量操作用@Transaction包裹(减少磁盘IO)、大表建索引(@Index)、避免在主线程查询(用协程Dispatchers.IO)、分页用Paging3集成。
Q4:WorkManager适合什么场景?
场景:需要保证执行的后台任务(App退出、设备重启也会执行)。典型:数据同步、日志上传、定期备份。
特点:保证执行(持久化到数据库)、支持约束条件(网络可用、充电中)、支持链式任务、支持周期任务(最小间隔15分钟)。
vs其他:AlarmManager(精确触发但不保证执行)、CoroutineScope(App进程存活才有效)。WorkManager内部根据API版本自动选择JobScheduler/AlarmManager。
追问:WorkManager最小间隔为什么15分钟?系统限制——避免过于频繁唤醒设备耗电。更短间隔的定时任务用前台服务+Handler。
Q5:ViewModel是怎么做到屏幕旋转不丢失数据的?
原理:ViewModel存储在ViewModelStore中。屏幕旋转时Activity重建,但ViewModelStore通过NonConfigurationInstances保留(不被销毁),新Activity获取旧的ViewModelStore。
Lifecycle:ViewModel感知生命周期。Activity finish时调用onCleared()清理资源。屏幕旋转时不调用onCleared(ViewModel存活)。
注意:ViewModel不持有Activity/Fragment引用(避免泄漏)。需要Context用AndroidViewModel。不要在ViewModel中保存UI状态(用SavedStateHandle)。
追问:SavedStateHandle是什么?ViewModel级别的Bundle——进程被杀后恢复时数据自动恢复。底层通过SavedStateRegistry在onSaveInstanceState中保存、onCreate中恢复。
Q6:LiveData的setValue和postValue区别?
setValue:必须在主线程调用。直接更新值并通知观察者。同步执行,立即生效。
postValue:可以在任意线程调用。内部post到主线程Handler执行setValue。异步执行,多次postValue只有末次值生效(合并更新)。
常见坑:主线程连续调用postValue两次,只有第二个值通知(Handler消息合并)。需要每次通知用setValue。
LiveData的问题:只能在主线程setValue、不支持操作符(需Transformations)、粘性事件问题(新观察者收到旧值,不适合一次性事件)。
追问:一次性事件用什么?SharedFlow(replay=0,新订阅者不收到旧值)、Channel(协程通道)、Event包装器。推荐SharedFlow。
Q7:Repository模式怎么和ViewModel配合?
Repository:数据仓库层,统一管理数据源(本地数据库+远程API)。ViewModel不直接访问数据库或网络,通过Repository获取数据。
数据流:RemoteDataSource(Retrofit)+ LocalDataSource(Room)→ Repository(决定数据源)→ ViewModel(观察变化)→ View(渲染)。
离线优先:Repository先返回本地缓存(Room),同时请求远程数据更新本地。用户始终能看到数据(即使离线),在线时自动刷新。Room返回LiveData/Flow实现自动观察。
追问:Repository应该单例吗?推荐单例。Repository管理数据源和缓存,多实例导致缓存不一致。
Q8:滴滴中级Android面怎么准备?
重点复习:MVP/MVVM对比、Dagger2/Hilt依赖注入、Room数据库(迁移)、WorkManager(适用场景)、ViewModel原理(屏幕旋转存活)、LiveData/Flow、Repository模式。
面试技巧:中级岗考架构选型——不只讲API用法,要能对比方案优缺点。比如"MVVM比MVP好在哪"、"WorkManager和AlarmManager怎么选"。结合项目讲选型决策过程。
面试Tips:滴滴中级面考架构能力——MVVM和ViewModel原理是必考题,Room和WorkManager也高频。Dagger2/Hilt依赖注入经常问。能讲清架构选型理由和项目应用经验加分明显。
下一篇进入滴滴高级Android——RxJava源码、Dagger2源码、R8/ProGuard混淆、多渠道构建。
从MVP迁移到MVVM的同学扣1,你觉得迁移过程最大的挑战是什么?
本系列连载中,关注不迷路,下一篇:滴滴高级Android工程师面试真题
系列简介:Android大厂面经连载,覆盖字节跳动、腾讯、阿里、美团等40+企业,从初级到架构师全岗位覆盖。每篇文章包含真实面试题+详细答案+代码示例,帮你拿到大厂Offer。