标准 Android 项目结构(MVVM + 分层架构)
你这个情况非常常见,尤其是刚接触 Android 或 Jetpack Compose 的时候。下面我用一个结构清晰、职责分明的项目分层指南来帮你理一理,解决“写哪都不对”的问题。
✅ 标准 Android 项目结构(MVVM + 分层架构)
com.example.app
│
├── data/ // 数据层:数据源、网络、数据库、模型
│ ├── model/ // 数据模型(如 User.kt, UpdateInfo.kt)
│ ├── network/ // Retrofit 接口定义、API请求
│ └── repository/ // 仓库层:组合调用多个数据源
│
├── domain/ // 领域层(可选):业务逻辑、用例(UseCase)
│ └── usecase/ // eg: CheckUpdateUseCase.kt
│
├── ui/ // 展示层:Activity、Fragment、Compose、ViewModel
│ ├── screen/ // 各个页面模块
│ │ ├── home/
│ │ │ ├── HomeScreen.kt
│ │ │ └── HomeViewModel.kt
│ │ └── update/
│ │ ├── UpdateScreen.kt
│ │ └── UpdateViewModel.kt
│ └── component/ // 公共组件,如 Button、Card、Dialog 封装
│
├── utils/ // 工具类,如 UpdateUtils.kt、DateUtils.kt
│
└── MainActivity.kt // 入口,通常作为导航容器
👇 各层该写什么?
位置 | 职责说明 |
---|---|
model/ |
定义数据结构(如从服务器拿到的 JSON 对象) |
network/ |
Retrofit 接口、HTTP 请求封装 |
repository/ |
管理数据来源(比如先从缓存拿,没有再请求) |
usecase/ (可选) |
把多个 Repository 操作组合起来形成“某个业务逻辑” |
viewmodel/ |
页面状态、调业务逻辑(usecase 或 repository),暴露状态给 UI |
ui/ |
展示界面(Compose),收集状态、响应事件 |
utils/ |
非依赖上下文的工具函数,适合封装成 object |
MainActivity.kt |
只做导航容器或顶层初始化 |
✅ 举个例子:检查更新功能应该怎么分
✔️ 1. model/UpdateInfo.kt
data class UpdateInfo(
val latestVersion: String,
val releaseNote: String,
val downloadUrl: String
)
✔️ 2. network/UpdateApi.kt
interface UpdateApi {
@GET("releases/latest")
suspend fun getLatestRelease(): Response<UpdateInfo>
}
✔️ 3. repository/UpdateRepository.kt
class UpdateRepository(private val api: UpdateApi) {
suspend fun fetchUpdate(): UpdateInfo {
return api.getLatestRelease().body()!!
}
}
✔️ 4. viewmodel/UpdateViewModel.kt
class UpdateViewModel(private val repo: UpdateRepository) : ViewModel() {
var updateInfo by mutableStateOf<UpdateInfo?>(null)
private set
var isLoading by mutableStateOf(false)
fun checkForUpdate() {
viewModelScope.launch {
isLoading = true
updateInfo = repo.fetchUpdate()
isLoading = false
}
}
}
✔️ 5. screen/update/UpdateScreen.kt
@Composable
fun UpdateScreen(vm: UpdateViewModel) {
val info = vm.updateInfo
val loading = vm.isLoading
Button(
onClick = { vm.checkForUpdate() },
enabled = !loading
) {
if (loading) {
CircularProgressIndicator()
} else {
Text("检查更新")
}
}
info?.let {
Text("最新版本:${it.latestVersion}")
}
}
✳️ 提示:如何开始重构?
- 从现有功能拆分出 ViewModel
- 再拆出 Repository 和网络部分
- 最后整理 model 和 utils 目录
想让结构清晰,记住一句话:
UI 不做逻辑,逻辑不操作网络,网络不关心 UI。
如果你愿意,我可以:
- 帮你一步步重构当前项目结构
- 或者基于你现有功能,帮你生成一套清晰结构模板
你更希望我现在从哪块开始帮你整理?(比如检查更新功能、登录、首页等)