整理自模拟面试,覆盖 MVVM / Lifecycle / LiveData / ViewModel / WorkManager / Navigation
| 模式 | 核心思想 | 缺点 |
|---|---|---|
| MVC | Activity 同时是 View + Controller | Activity 臃肿,难测试 |
| MVP | Presenter 通过接口与 View 通信 | Presenter 持有 View 引用,内存泄漏风险;接口繁琐 |
| MVVM | ViewModel 暴露数据,View 观察订阅,数据驱动 UI | 简单页面略过度设计 |
| MVI | 单向数据流,用户操作 → Intent → 唯一 UiState → 渲染 | 样板代码多 |
MVVM 三层:
- Model:数据层,Repository / 数据库 / 网络请求
- ViewModel:持有 UI 状态,处理业务逻辑,通过 LiveData/StateFlow 暴露给 View
- View:Activity/Fragment,只观察数据、渲染 UI、转发用户操作,不含业务逻辑
ViewModelProvider.get() 创建,到 Activity 真正销毁(finish())时销毁SavedStateHandle 补救ViewModelStore 里ComponentActivity 重写 onRetainNonConfigurationInstance(),把 ViewModelStore 塞入 NonConfigurationInstancesgetLastNonConfigurationInstance() 取回,ViewModel 得以保留ViewModelStore 定义在 androidx.lifecycle,保留机制由 androidx.activity.ComponentActivity 提供AppCompatActivity → FragmentActivity → ComponentActivity(实现 ViewModelStoreOwner)
by activityViewModels():生命周期跟 Activity,多 Fragment 共享by viewModels():生命周期跟 Fragment 自身by navGraphViewModels():生命周期跟 NavGraph,粒度更细INITIALIZED / CREATED / STARTED / RESUMED / DESTROYEDON_CREATE / ON_START / ON_RESUME / ON_PAUSE / ON_STOP / ON_DESTROYLifecycleOwner 接口的类可提供 Lifecycle 对象(ComponentActivity / Fragment 均已实现)第一层:谁触发
- ComponentActivity.onCreate() 注入无 UI 的 ReportFragment
- ReportFragment 各生命周期回调调用 dispatch(event) → 分发给 LifecycleRegistry
- API 29+ 也用 registerActivityLifecycleCallbacks,但 ReportFragment 兼容性更好
第二层:LifecycleRegistry 怎么管理
- 内部维护当前 State + FastSafeIterableMap(存所有 Observer)
- 收到 Event → 推进自身 State → 同步所有 Observer 的 State(循环而非递归,避免栈溢出)
第三层:Observer 怎么感知
- 旧方式:@OnLifecycleEvent 注解,反射调用,已废弃
- 新方式:实现 DefaultLifecycleObserver,重写对应方法,编译期确定,无反射开销
STARTED / RESUMED 状态时分发数据LifecycleOwner 销毁时自动移除 Observer,不会内存泄漏observe(lifecycleOwner, observer) 时,LiveData 拿到 lifecycle,包装成 LifecycleBoundObserverLifecycleBoundObserver.onStateChanged() → 判断是否活跃 → 决定是否分发数据| 问题 | 说明 |
|---|---|
| 粘性事件 | 新 Observer 注册立刻收到上次的值,一次性事件(Toast/导航)容易重复触发 |
| 多 LiveData 状态不一致 | 分散在多个 LiveData,组合逻辑复杂时容易出问题 |
| 不支持背压 | 快速连续 postValue 只保留最后一次,中间值丢弃 |
repeatOnLifecycle(Lifecycle.State.STARTED) 收集,同样生命周期安全LiveData<T>)JobScheduler(API 23+)→ GCM → AlarmManager,优先系统级调度Result.retry() + BackoffPolicy.EXPONENTIAL/LINEAR,状态持久化,重启后继续计数// 定义任务(优先用 CoroutineWorker)
class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
doSync()
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
// 提交任务
val request = OneTimeWorkRequestBuilder<SyncWorker>()
.setInputData(workDataOf("key" to "value"))
.setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.SECONDS)
.build()
// 避免重复入队
WorkManager.getInstance(context).enqueueUniqueWork(
"sync_task",
ExistingWorkPolicy.KEEP,
request
)
// 周期任务(最小间隔 15 分钟)
val periodicRequest = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES).build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"periodic_sync", ExistingPeriodicWorkPolicy.KEEP, periodicRequest
)
// 任务链
WorkManager.getInstance(context).beginWith(taskA).then(taskB).then(taskC).enqueue()
doWork() 超时限制 10 分钟,超时自动失败Data 传输大小限制 10KB,大数据存 Room/文件再传 ID// 普通跳转
findNavController().navigate(R.id.action_home_to_detail)
// Safe Args(推荐,编译期类型安全)
val action = HomeFragmentDirections.actionHomeToDetail(userId = "123")
findNavController().navigate(action)
// 接收参数
val args: DetailFragmentArgs by navArgs()
val userId = args.userId
// 回退栈操作
findNavController().popBackStack()
findNavController().popBackStack(R.id.homeFragment, inclusive = false)
// 跳转时清空回退栈(登录成功跳首页)
findNavController().navigate(R.id.homeFragment, navOptions {
popUpTo(R.id.loginFragment) { inclusive = true }
})
findNavController() 在 onViewCreated 之后调用,onCreate 里调用会空指针currentDestinationNavigationUI.setupWithNavController)by navGraphViewModels(),生命周期比 activityViewModels 更精确| 知识点 | 速记 |
|---|---|
| ViewModel 生命周期 | 比 Activity 长,配置变更不销毁,靠 NonConfigurationInstances 保留 |
| Lifecycle 原理 | ReportFragment 触发 → LifecycleRegistry 状态机 → 通知 Observer |
| LiveData 安全 | LifecycleBoundObserver 判断活跃态,自动注销不泄漏 |
| WorkManager 可靠 | 持久化 + 多调度器 + 约束监听 + 重试退避 |
| Navigation 跳转 | NavController.navigate() + Safe Args 类型安全 |