View 规范
页面视图层遵循“Route -> Screen -> Content”三级结构。该规范来源于项目内部的实践总结,现整理为对外文档,便于编写 Compose 页面时快速套用。
1. Route 层
- 职责:作为页面入口,注入 ViewModel 并收集所有
StateFlow。 - 命名:
${PageName}Route,需带完整注释(描述 + 参数)。 - 实现要点:
- 只能通过
collectAsState()获取状态,禁止直接访问 ViewModel 字段。 - 负责将所有回调(
onBackClick、onRetry、弹窗切换等)传递给下一层。
- 只能通过
kotlin
/**
* 商品详情路由入口
*
* @param viewModel 页面 ViewModel
*/
@Composable
internal fun GoodsDetailRoute(
viewModel: GoodsDetailViewModel = hiltViewModel()
) {
// 页面 UI 状态
val uiState by viewModel.uiState.collectAsState()
// 规格弹窗状态
val specModalVisible by viewModel.specModalVisible.collectAsState()
// ...更多状态
GoodsDetailScreen(
uiState = uiState,
specModalVisible = specModalVisible,
onBackClick = viewModel::navigateBack,
onRetry = viewModel::retryRequest,
onShowSpecModal = viewModel::showSpecModal,
// ...更多回调
)
}2. Screen 层
- 职责:负责页面骨架、Loading/Empty/Error 切换,以及
Scaffold、BaseNetWorkView等容器。 - 命名:
${PageName}Screen。 - 参数:路由层传下来的所有状态、回调,类型应尽量可空或提供默认值,以便
@Preview使用。 - 实现要点:
- 仅在此层处理 Loading/Retry/空页面。
- 成功态通过
contentlambda 将数据传给 Content 层。
kotlin
/**
* 商品详情界面
*
* @param uiState 商品详情 UI 状态
* @param specModalVisible 规格弹窗是否显示
* @param onRetry 重试请求
* @param onShowSpecModal 显示规格弹窗
*/
@Composable
internal fun GoodsDetailScreen(
uiState: BaseNetWorkUiState<GoodsDetail>,
specModalVisible: Boolean,
onRetry: () -> Unit,
onShowSpecModal: () -> Unit,
// ...
) {
BaseNetWorkView(
uiState = uiState,
onRetry = onRetry
) { detail ->
GoodsDetailContent(
data = detail,
specModalVisible = specModalVisible,
onShowSpecModal = onShowSpecModal,
// ...
)
}
}3. Content 层
- 职责:展示成功态 UI,不直接依赖 ViewModel。
- 命名:
${PageName}Content或${PageName}ContentView。 - 参数:都为非空具体类型(如
GoodsDetail、Boolean),确保可独立预览。
kotlin
/**
* 商品详情成功态
*
* @param data 商品详情数据
* @param specModalVisible 规格弹窗状态
* @param onShowSpecModal 显示规格弹窗
*/
@Composable
private fun GoodsDetailContent(
data: GoodsDetail,
specModalVisible: Boolean,
onShowSpecModal: () -> Unit,
// ...
) {
// 只负责绘制 UI,可自由拆分子组件
}4. 预览规范
- 每个 Screen 需提供浅色/深色两套
@Preview,注入BaseNetWorkUiState.Success(mockData())。 - Content 层若依赖复杂数据,建议提供
mockData()方法或preview扩展,方便 Preview 与单元测试复用。
kotlin
/**
* 商品详情预览(浅色)
*/
@Preview(showBackground = true)
@Composable
internal fun GoodsDetailScreenPreview() {
AppTheme {
GoodsDetailScreen(
uiState = BaseNetWorkUiState.Success(mockGoodsDetail()),
specModalVisible = false,
onRetry = {},
onShowSpecModal = {}
)
}
}5. 注释与命名
- 所有 Route/Screen/Content/Preview 须保持 KDoc(描述与参数说明)。
- 文件名使用
${PageName}Screen.kt,Route/Screen/Content/Preview 均放在同一文件中,便于查阅。 - 局部组件若可复用,移动到模块内的
component/目录。
6. 资源与文案
- 避免硬编码文案,统一放在
res/values/strings.xml(项目全局)中。若未来拆分多模块,再单独维护。 - 颜色、尺寸、圆角使用
core/designsystem/core/ui的常量,以保持全局视觉一致。
7. 校验清单
- [ ] Route 只负责收集状态与转发回调,不包含业务逻辑。
- [ ] Screen 处理 Loading/Error/Retry,Content 只绘制成功态。
- [ ] 所有 Compose 函数具备注释,Preview 至少包含浅/深色两套。
- [ ] UI 不直接调用 ViewModel,所有交互通过回调完成。
遵循上述规范即可确保 Feature 层页面结构清晰,与 ViewModel 契约稳定,也让模板自动生成的代码直接可用。