Jetpack 组件按职责天然分族:数据与状态、UI 绑定、生命周期、依赖注入。同族组件往往配合使用——ViewModel 暴露 LiveDataROOM 查询能返回 LiveDataFlowDataStoreROOM 按数据形态分工。

一、数据与状态:ViewModel 管状态、LiveData 管观察、ROOM 与 DataStore 分管存储

ViewModel:状态从组件生命周期里抽出来

ViewModel 把界面状态从 Activity/Fragment 生命周期里抽出来,配置变更后由 ViewModelStore 按 key 复用同一实例。onCleared 里取消协程与解绑。AndroidViewModel 可拿 Application,不要持有 ActivityViewSavedStateHandle 能在进程被杀后恢复。配合 LiveData/StateFlow 向外暴露不可变状态。FactoryCreationExtras 处理有参构造;Hilt 则用 @HiltViewModel。共享 ViewModelactivityViewModels(),注意作用域过大导致泄漏。测试可用 ViewModel 纯单元测,不必起 ActivityviewModelScope 默认 Main.immediate,切 IO 时记得把结果切回 UI 线程。

LiveData:带生命周期的可观察数据

LiveData 是带生命周期的可观察数据:STARTED 才分发,DESTROYED 自动移除。observeLifecycleOwnerobserveForever 必须手动 removepostValue 可在后台线程,setValue 必须主线程。粘性/倒灌:新订阅者会立刻收到最后一条,页面重建可能重复消费事件;单次事件可用 SingleLiveEvent 或封装 Event 包装类。MediatorLiveData 适合组合多个源。LiveDataBus 用总线解耦,但隐式依赖难追踪,优先 ViewModel 共享。不要在 observe 里再改同一 LiveData 造成循环。测试用 InstantTaskExecutorRule

ROOM:把 SQLite 类型安全化

RoomEntityDaoDatabase 三件套把 SQLite 类型安全化。查询可返回 LiveDataFlow,在 ViewModel 里收集。版本升级写 Migration,测试用 MigrationTestHelper;失败策略有 fallbackToDestructiveMigration,会丢数据。exportSchema 便于审差异。预填充可用 createFromAsset。加密常用 SQLCipher 封装。主线程查询默认禁止,必须指定 allowMainThreadQueries 仅调试。索引与外键写在 Entity 上。TypeConverter 处理枚举与日期。多表关系用 @Relation 小心 N+1。和 DataStore 分工:结构化数据走 Room,简单配置走 DataStore

DataStore:SharedPreferences 的继任者

DataStore 是 Jetpack 对 SharedPreferences 的继任:Preferences DataStore 用键值,Proto DataStore 用强类型 protobuf。读写都走协程/Flow,避免主线程卡顿与 apply 队列导致的 ANR。迁移 SP 可用 SharedPreferencesMigration。多进程要用 MultiProcessDataStore 或换 MMKV。更新用 updateData 保证原子读写,不要先 readwrite 产生竞态。序列化异常要提供 corruptionHandler。文件落在 files/datastore。测试可用测试调度器注入。和 Room 的边界:少量配置用 DataStore,关系数据仍走数据库。

三者按数据形态分层:界面状态用 ViewModel + LiveData/StateFlow 暴露;结构化、可查询的数据用 ROOM;仅键值/强类型配置用 DataStore,不是替代关系。

二、UI 绑定:DataBinding 与 ViewBinding 怎么选

DataBinding:在 XML 里写表达式

DataBinding 在 XML 里写表达式,编译期生成 Binding 类,把 View 与数据对象连起来。事件绑定可用 lambda 或方法引用;include 布局会生成子 Binding。自定义属性靠 @BindingAdapter,图片加载、本地资源可用重载区分。双向绑定用 @={},数据侧用 BaseObservableObservableField,记得 notifyRecyclerView 把 item Binding 放进 ViewHolder。和 ViewModel+LiveData 搭配时,lifecycleOwner 要设对,否则观察不到。相比 ViewBinding,它更重、构建更慢。新项目能不用就不用。注意循环绑定与主线程刷新。BindingAdapter 要做成静态且无副作用。

ViewBinding:编译期生成的类型安全绑定

ViewBinding 在编译期为每个布局生成绑定类,字段对应带 id 的控件,类型安全且空安全。ActivityinflateFragment 要在 onDestroyView_binding 置空,避免持有旧视图。include 会嵌套生成子 Binding。与 DataBinding 不同,它不做表达式和双向绑定,APT 开销更小。merge 根布局要用 bind(parent) 而不是 inflateRecyclerViewViewHolder 持有 item Binding 即可,不必再 findViewById。模块开启 viewBinding true 后注意资源混淆与 flavor 下布局同名。自定义 View 内部也可 inflate Binding。迁移 ButterKnife 时先替换注解字段,再删掉 unbinder。

只想要类型安全、空安全的视图引用用 ViewBinding(APT 开销小、构建快);确实需要在 XML 里写表达式、做双向绑定时才用 DataBinding,且注意构建成本。

三、生命周期:LifeCycle 与 AppStartUp

Lifecycle:把生命周期建模成状态机

LifecycleON_CREATEON_DESTROY 建模成状态机,Observer 只在至少 STARTED 时活跃。LifecycleOwner 由组件实现,LifecycleRegistry 派发事件。DefaultLifecycleObserver 比注解更清晰。LifecycleServiceService 也能被观察;ProcessLifecycleOwner 表示整个应用前后台,适合埋点与连接管理,不要拿它当单 Activity 生命周期。repeatOnLifecycle 是协程里收集 Flow 的推荐写法。自定义 Owner 时要按序 dispatch,避免在 DESTROYED 后再加观察者。与 ViewTreeLifecycleOwner 结合,Compose/自定义 View 才能正确感知窗口销毁。

App Startup:把初始化收拢成拓扑序

App StartupContentProvider 散落的初始化收拢到 InitializationProvider,用 Initializer 声明依赖并按拓扑序执行。可在 manifest 里 disable 自动发现,改由 AppInitializer 按需触发,避免冷启动拖死 Application.onCreate。实现 Initializer<T> 时要声明 dependencies()WorkManagerEmojiCompat 都是这套模型。注意主线程与后台线程:库初始化若不依赖 UI,尽量推到后台并用跟踪测耗时。多模块工程里让每个 feature 提供自己的 Initializer,主工程只调用图的入口。若与 Hilt 搭配,先保证 Application 已创建再去取 EntryPoint,否则容易遇到过早注入。

需要随组件生命周期启停的逻辑(协程、连接、观察)都基于 Lifecycle;多库冷启动初始化拖慢 Application.onCreate 时,用 App Startup 收敛并按拓扑序执行。

四、依赖注入:Hilt 在标准组件上套一层

HiltDagger 上套标准组件:SingletonComponentActivityRetainedViewModelActivityFragment@HiltAndroidApp 生成入口,@AndroidEntryPoint 让页面可 @Inject。模块用 @InstallIn 声明作用域。ViewModel@HiltViewModel + @Inject 构造,AssistedInject 处理运行时参数。多绑定 @IntoSet/@IntoMap 适合插件化初始化。测试用 @HiltAndroidTest@UninstallModules 替换假实现。常见坑是作用域不匹配:把 Activity 依赖放进 SingletonHilt 不直接支持跨模块可选依赖,需要用入口聚合。编译慢时可开 incremental 并减少不必要的 @InstallIn 扫包。

需要统一、可测试的依赖装配时上 Hilt;配合 ViewModel@HiltViewModel,配合 App Startup 时注意 Application 创建顺序。

附:新老替代与分工对照表

维度 老 / 另一种 新 / 继任 判断与边界
键值配置存储 SharedPreferencesapply 队列、主线程风险) DataStore(Preferences/Proto) DataStore 是 SP 的继任,读写走协程/Flow,避免主线程卡顿与 ANR
视图绑定 findViewById / ButterKnife ViewBinding 类型安全、空安全,APT 开销小;ButterKnife 迁移先换注解字段再删 unbinder
XML 表达式绑定 无(手写 setText 等) DataBinding 更重、构建更慢,新项目能不用就不用;仅需绑定用 ViewBinding
结构化数据 SQLite / 不该塞 DataStore ROOM 关系数据走 ROOM,少量配置才走 DataStore
数据流观察 LiveData(界面状态) Flow(协程数据流,ROOM/DataStore 均可返回) LiveDataViewModel 暴露界面状态;FlowrepeatOnLifecycle 收集,二者按场景分工而非简单替换
散落初始化 各库 ContentProvider App Startup 收拢成初始化拓扑序,避免冷启动拖死 Application.onCreate