Jetpack 面试知识点整理

整理自模拟面试,覆盖 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、转发用户操作,不含业务逻辑


二、ViewModel

生命周期

底层原理

继承链

AppCompatActivity → FragmentActivity → ComponentActivity(实现 ViewModelStoreOwner)

Fragment 共享 ViewModel 注意点


三、Lifecycle

核心概念

底层原理(三层)

第一层:谁触发
- ComponentActivity.onCreate() 注入无 UI 的 ReportFragment
- ReportFragment 各生命周期回调调用 dispatch(event) → 分发给 LifecycleRegistry
- API 29+ 也用 registerActivityLifecycleCallbacks,但 ReportFragment 兼容性更好

第二层:LifecycleRegistry 怎么管理
- 内部维护当前 State + FastSafeIterableMap(存所有 Observer)
- 收到 Event → 推进自身 State → 同步所有 Observer 的 State(循环而非递归,避免栈溢出)

第三层:Observer 怎么感知
- 旧方式:@OnLifecycleEvent 注解,反射调用,已废弃
- 新方式:实现 DefaultLifecycleObserver,重写对应方法,编译期确定,无反射开销


四、LiveData

核心行为

与 Lifecycle 的关系

常见问题

问题 说明
粘性事件 新 Observer 注册立刻收到上次的值,一次性事件(Toast/导航)容易重复触发
多 LiveData 状态不一致 分散在多个 LiveData,组合逻辑复杂时容易出问题
不支持背压 快速连续 postValue 只保留最后一次,中间值丢弃

LiveData vs StateFlow


五、WorkManager

可靠性保证(五层)

  1. 持久化:任务写入 Room 数据库,进程被杀/重启后从数据库恢复,不丢任务
  2. 多调度器兜底JobScheduler(API 23+)→ GCM → AlarmManager,优先系统级调度
  3. 约束检查:监听系统广播,约束满足才执行(网络、充电等),不满足则挂起等待
  4. 重试与退避Result.retry() + BackoffPolicy.EXPONENTIAL/LINEAR,状态持久化,重启后继续计数
  5. GreedyScheduler:进程活跃时立刻执行,降低延迟;系统调度器负责进程死后的可靠性

常见写法

// 定义任务(优先用 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()

注意点


核心概念

常见写法

// 普通跳转
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 }
})

注意点


七、一句话速记

知识点 速记
ViewModel 生命周期 比 Activity 长,配置变更不销毁,靠 NonConfigurationInstances 保留
Lifecycle 原理 ReportFragment 触发 → LifecycleRegistry 状态机 → 通知 Observer
LiveData 安全 LifecycleBoundObserver 判断活跃态,自动注销不泄漏
WorkManager 可靠 持久化 + 多调度器 + 约束监听 + 重试退避
Navigation 跳转 NavController.navigate() + Safe Args 类型安全