随着 Android 生态的飞速发展,从 Java 到 Kotlin,从 XML 到 Jetpack Compose,从 Callback 到 Coroutines/Flow,开发模式已经发生了翻天覆地的变化。构建一个高质量、可维护、可扩展的 Android 应用,核心在于架构的合理性 与工程化的规范性。
本文将围绕当前 Android 开发的最佳实践,结合最新的技术框架,深入解析项目工程的分层架构设计及整体数据交互流程。
未来不可知,本文基于2025年当下,安卓的开发实践撰文。
一、核心技术栈选型
现代 Android 开发应优先采用经过 Google 官方推荐且社区验证成熟的库,以提高开发效率和代码质量。
| 领域 | 推荐技术 | 理由 |
|---|---|---|
| 语言 | Kotlin (100%) | 空安全、协程支持、语法简洁,是 Android 开发首选。 |
| UI 框架 | Jetpack Compose | 声明式 UI,代码量少,状态驱动,替代传统 View 体系。 |
| 异步处理 | Coroutines + Flow | 结构化并发,流式数据处理,完美契合网络请求与本地数据监听。 |
| 依赖注入 | Hilt | 基于 Dagger,专为 Android 打造,减少大量样板代码。 |
| 网络请求 | Retrofit + OkHttp | 行业标准,配合 Kotlinx Serialization 进行高效 JSON 解析。 |
| 本地存储 | Room | 强大的 SQLite 抽象层,原生支持 Flow 返回实时观察数据。 |
| 图片加载 | Coil | 专为 Kotlin 和 Compose 构建,轻量且基于 Coroutines。 |
| 构建管理 | Gradle Version Catalogs | 类型安全的构建脚本,利用 libs.versions.toml 统一管理依赖版本。 |
二、分层架构设计
现代 Android 架构的核心理念是 关注点分离 和 单一数据源 。我们推荐采用基于 清洁架构 变体的三层架构模式。
依赖规则: 外层可以依赖内层,内层绝对不能依赖外层。Domain 层必须是纯 Kotlin 模块,不包含任何 Android 框架代码。
1. 表现层
- 职责:显示数据,响应用户交互。
- 组成 :
- UI (Compose) :
@Composable函数,只负责渲染,不包含业务逻辑。 - ViewModel :持有 UI 状态 (
StateFlow),调用 Domain 层的 Use Case。
- UI (Compose) :
- 最佳实践:UI 状态不可变,事件通过 Intent/Lambda 向上传递,数据通过 State 向下流动。
2. 领域层
- 职责:封装核心业务逻辑,是应用的"大脑"。
- 组成 :
- Use Cases (Interactors) :原子化的业务操作(如
GetUserProfileUseCase)。 - Entities:纯业务模型。
- Repository Interfaces:定义数据获取的契约,不关心数据来源。
- Use Cases (Interactors) :原子化的业务操作(如
3. 数据层
- 职责:管理数据的获取、缓存和持久化。
- 组成 :
- Repository Implementations:实现 Domain 层的接口,决定数据是从网络还是数据库读取。
- Remote/Local DataSource:Retrofit 接口与 Room DAO。
- DTOs (Data Transfer Objects):网络或数据库专用模型,需在此层 Mapper 转换为 Domain Entities。
- 最佳实践:实现"离线优先"策略,利用 Room 的 Flow 特性实现数据的自动同步与更新。
三、整体交互流程图
为了更直观地理解上述分层架构在实际代码中的运行机制,以下是用户触发一次操作(如"获取用户数据")的完整交互流程图。事件自顶向下传递,数据自底向上回流:
- 触发事件
- 调用方法
- 执行业务
- 获取数据
5a. 发起网络请求
6a. 返回 JSON
5b. 写入/读取缓存 - 观察数据变更
- 映射 DTO 为 Entity 并返回
- 返回业务结果
- 更新 UiState
- 重组渲染新界面
用户操作
Jetpack Compose
ViewModel
Use Case
Repository Impl
Retrofit API
Room Database
四、UDF 实践
单向数据流 (UDF)
现代架构的核心数据模式是 单向数据流。状态从数据层经过 ViewModel 流向 UI,事件从 UI 经过 ViewModel 流向数据层,两者永远不反向流动。
单向数据流 --- 状态向下流动,事件向上传递
典型数据流时序
- 用户触发事件 :用户点击按钮、滚动列表或输入文本,Composable 通过
onClick回调向 ViewModel 发送一个UiEvent。 - ViewModel 处理事件 :ViewModel 的处理函数收到事件,根据事件类型调用对应的 UseCase 或 Repository 方法(
suspend函数)。 - UseCase 执行业务逻辑:UseCase 组合一个或多个 Repository 调用,执行数据验证、过滤、排序等业务规则后返回结果。
- Repository 协调数据源 :Repository 实现类根据策略(缓存优先、网络优先等)从 Room 数据库或 Retrofit API 获取数据,并以
Flow<T>形式持续发射。 - ViewModel 更新状态 :ViewModel 收到数据后,通过
_uiState.update { }更新MutableStateFlow,将新的UiState发射出去。 - UI 重组渲染 :Composable 通过
collectAsState()订阅状态变化,当新状态到达时触发重组,界面自动更新。
常见反模式
避免在 Composable 中直接调用 Repository------这会绕过 ViewModel 导致状态管理混乱。也不要在 ViewModel 中持有 Context 引用,这会造成内存泄漏。始终让数据流经过 UI → ViewModel → UseCase → Repository 的完整链路。
代码实现示例
基于上述 UDF 原则,以下是标准的代码实现方式:
1. ViewModel 负责处理逻辑并更新状态
kotlin
@HiltViewModel
class UserProfileViewModel @Inject constructor(
private val getUserProfileUseCase: GetUserProfileUseCase // 注入 Domain 层 UseCase
) : ViewModel() {
// 1. 定义私有的可变状态
private val _uiState = MutableStateFlow(UserProfileUiState())
// 2. 暴露不可变的公开状态供 UI 订阅
val uiState: StateFlow<UserProfileUiState> = _uiState.asStateFlow()
// 3. 接收 UI 的事件
fun onRefresh() {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) } // 显示加载框
try {
// 调用 Domain 层执行业务
val profile = getUserProfileUseCase()
_uiState.update { it.copy(isLoading = false, data = profile) } // 成功更新状态
} catch (e: Exception) {
_uiState.update { it.copy(isLoading = false, error = e.message) } // 失败更新状态
}
}
}
}
2. Compose UI 负责渲染状态并分发事件
kotlin
@Composable
fun UserProfileScreen(
viewModel: UserProfileViewModel = hiltViewModel()
) {
// 订阅状态,生命周期感知
val state by viewModel.uiState.collectAsStateWithLifecycle()
// 根据 state 渲染 UI (状态向下流动)
if (state.isLoading) {
CircularProgressIndicator()
} else if (state.error != null) {
ErrorView(message = state.error)
} else {
ProfileContentView(profile = state.data)
}
// 下拉刷新时,触发事件 (事件向上传递)
SwipeRefresh(
onRefresh = { viewModel.onRefresh() }
)
}
五、总结
构建现代化的 Android 工程是一项系统性工程,核心在于高内聚低耦合的设计原则。通过采用清晰的分层架构 (Presentation、Domain、Data),我们确保了业务逻辑的独立性和可测试性;通过拥抱单向数据流 (UDF) 和 Kotlin Flow,我们理清了复杂的数据流转链路,极大减少了状态管理的 Bug。
在实际应用中,Jetpack Compose 的声明式范式完美契合了这种架构,结合 Hilt 的依赖注入和 Retrofit/Room 的数据管理,使得整个应用不仅代码结构清晰,而且具备极高的可维护性与健壮性。掌握并熟练应用这套架构体系,是开发高质量、团队协作型 Android 应用的基石。
(END)