Now in Android 项目架构解析与学习指南
前言
Now in Android 是 Google 官方推出的一个现代化 Android 应用开发示例项目,它展示了当前 Android 平台推荐的最佳实践和架构模式。本文将深入解析该项目的架构设计,帮助开发者理解其分层结构、核心组件以及各层之间的交互方式。
架构设计目标与要求
Now in Android 的架构设计遵循以下几个核心原则:
- 严格遵循官方架构指南:完全基于 Android 官方推荐的架构模式构建
- 易于理解:避免使用过于实验性的技术,保持代码简洁明了
- 支持团队协作:架构设计要便于多位开发者同时在同一个代码库上工作
- 测试友好:支持本地测试和仪器化测试,便于持续集成(CI)
- 构建效率:最小化构建时间,提高开发效率
整体架构概述
Now in Android 采用典型的三层架构设计:
- 数据层(Data Layer):负责数据获取和持久化
- 领域层(Domain Layer):包含业务逻辑和用例
- UI层(UI Layer):处理界面展示和用户交互

注意:Android 官方架构与其他架构模式(如"Clean Architecture")有所不同。其他架构中的概念可能不适用或以不同方式应用。
该架构采用响应式编程模型,遵循单向数据流(Unidirectional Data Flow)原则:
- 上层对下层的变化做出反应
- 事件向下流动
- 数据向上流动
数据流通过 Kotlin Flow 实现,构建了一个响应式的数据管道系统。
实战案例:For You 屏幕新闻展示流程
让我们通过一个具体场景来理解架构各层如何协作:当应用首次运行时,从远程服务器加载新闻资源列表并显示给用户的过程。

详细步骤解析
| 步骤 | 描述 | 关键代码 |
|---|---|---|
| 1 | 应用启动时,通过 WorkManager 安排同步所有仓库的任务 | Sync.initialize |
| 2 | ForYouViewModel 调用 GetUserNewsResourcesUseCase 获取新闻资源流 | 搜索 NewsFeedUiState.Loading |
| 3 | 用户数据仓库从 Proto DataStore 获取 UserData 流 | NiaPreferencesDataSource.userData |
| 4 | WorkManager 执行同步任务,调用新闻仓库与远程数据源同步 | SyncWorker.doWork |
| 5 | 新闻仓库调用 Retrofit 执行实际 API 请求 | OfflineFirstNewsRepository.syncWith |
| 6 | Retrofit 调用远程服务器 REST API | RetrofitNiaNetwork.getNewsResources |
| 7 | Retrofit 接收网络响应 | RetrofitNiaNetwork.getNewsResources |
| 8 | 新闻仓库将远程数据与本地 Room 数据库同步 | OfflineFirstNewsRepository.syncWith |
| 9 | 数据库变更时,新闻资源流会发出新数据 | NewsResourceDao.getNewsResources |
| 10 | 新闻仓库转换数据库模型为公共模型 | OfflineFirstNewsRepository.getNewsResources |
| 11 | 用例组合新闻资源和用户数据生成用户新闻资源 | GetUserNewsResourcesUseCase.invoke |
| 12 | ViewModel 更新状态为 Success,UI 渲染屏幕 | 搜索 NewsFeedUiState.Success |
深入各层架构
数据层设计
数据层作为应用的单一数据源,采用"离线优先"策略实现:

核心特点
-
数据读取:
- 以数据流形式暴露数据
- 客户端必须准备好响应数据变化
- 从本地存储读取作为唯一真实来源
-
数据写入:
- 通过挂起函数提供写操作
- 调用方需确保适当的执行作用域
-
数据源类型:
- Room/SQLite:持久化关系型数据
- Proto DataStore:持久化非结构化用户偏好数据
- Retrofit:远程API数据访问
-
数据同步:
- 仓库负责协调本地与远程数据
- 采用指数退避策略处理错误
- 通过 WorkManager 实现后台同步
领域层设计
领域层包含用例(Use Cases),这些是单一可调用类,封装了业务逻辑:
- 每个用例有一个
invoke方法 - 主要作用是简化和消除 ViewModel 中的重复逻辑
- 组合和转换来自仓库的数据
例如,GetUserNewsResourcesUseCase 组合了来自新闻仓库的 NewsResource 流和用户数据仓库的 UserData 流,生成 UserNewsResource 流供 ViewModel 使用。
当前版本中,领域层不包含事件处理逻辑,事件由UI层直接调用仓库方法处理。
UI层设计
UI层由以下组件构成:
- UI元素:使用 Jetpack Compose 构建
- ViewModel:管理UI相关数据和逻辑

UI状态建模
UI状态使用密封接口和不可变数据类建模:
- 确保UI状态始终反映底层应用数据
- UI元素处理所有可能状态
例如,For You 屏幕的新闻源状态 NewsFeedUiState 有两种可能:
Loading:数据加载中Success:数据加载成功,包含新闻资源列表
数据流转换
ViewModel 将来自用例或仓库的冷流(Cold Flow):
- 通过
combine或map转换为单一UI状态流 - 使用
stateIn转换为热流(Hot Flow) - UI元素可以读取流中的最后已知状态
用户交互处理
用户操作通过方法调用从UI传递到ViewModel:
- UI元素接收lambda表达式形式的方法引用
- 用户交互触发这些方法调用
- ViewModel 处理动作并通知相应仓库
最佳实践总结
- 严格分层:明确划分数据、领域和UI层职责
- 单向数据流:确保数据流动方向清晰可预测
- 响应式编程:充分利用Kotlin Flow处理异步数据
- 不可变状态:UI状态使用不可变对象,避免副作用
- 测试友好:各层解耦设计便于单元测试和集成测试
通过 Now in Android 项目的架构分析,我们可以看到现代Android应用开发的推荐模式和最佳实践。这种架构设计不仅保证了应用的健壮性和可维护性,也为团队协作和持续集成提供了良好基础。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



