ViewModel 规范
ViewModel 是 Feature 层与 Core 层的桥梁:负责请求仓库、管理弹窗/加载状态,并以 StateFlow 的形式提供给 Route 层。以下约定整理自项目内部的编码规范与现有业务示例。
基类选择
| 场景 | 基类 | 说明 |
|---|---|---|
| 无网络/纯导航 | BaseViewModel | 仅持有 AppNavigator、UserState,封装导航方法。 |
| 非分页网络请求 | BaseNetWorkViewModel<T> | 自带 BaseNetWorkUiState<T>、executeRequest()、retryRequest()。 |
| 分页/列表 | BaseNetWorkListViewModel<T> | 扩展下拉刷新、上拉加载状态。 |
字段与注释
- 类注释和方法注释必须包含功能描述与参数说明,方便团队协作。
StateFlow命名使用完整语义,例如couponModalVisible、specModalVisible。- 私有可变流
_xxx+ 公共只读xxx的约定保持统一:
kotlin
private val _specModalVisible = MutableStateFlow(false)
val specModalVisible: StateFlow<Boolean> = _specModalVisible.asStateFlow()路由参数读取
使用 SavedStateHandle.toRoute<Route>() 获取类型安全参数,并缓存下来:
kotlin
private val route = savedStateHandle.toRoute<UserRoutes.AddressDetail>()
private val addressId = route.addressId状态收集
Route 层必须通过 collectAsState() 订阅状态:
kotlin
val uiState by viewModel.uiState.collectAsState()
val couponModalVisible by viewModel.couponModalVisible.collectAsState()避免在 Screen/Content 层直接访问 ViewModel 字段,以免破坏可组合式更新。
UI 交互状态
所有 UI 交互(弹窗、动画、刷新)都应该通过 StateFlow 暴露:
kotlin
fun showCouponModal() { _couponModalVisible.value = true }
fun hideCouponModal() { _couponModalVisible.value = false }Route 层收到状态后传递给 Screen/Content,避免在 Content 里使用 remember 保存业务状态。
导航与结果
- 使用
navigate(route)、navigateBack()、navigateBackTo()、popBackStackWithResult()等封装方法。 - 父页面需要刷新时,子页面调用
popBackStackWithResult(RefreshResultKey, true),父页面在 Route 层通过observeRefreshState()自动响应。
校验清单
- [ ] 类/方法注释完整,说明用途与参数。
- [ ] Mutable 状态全部封装为私有
_xxx,仅暴露只读StateFlow。 - [ ] Route 层仅通过
collectAsState()访问状态,Screen/Content 不直接引用 ViewModel。 - [ ] 所有交互(弹窗、导航、刷新)都封装成清晰的函数,供 UI 层调用。
- [ ] 网络请求通过
requestApiFlow()+executeRequest()驱动,Loading/Error 已交给基类处理。
遵循这些规则即可让 Feature 层的 ViewModel 与 Core 能力无缝协作,也方便团队在其他业务模块中快速复用。