项目初始化:用 Android Studio 搭建 Compose 项目
嗯,这一章我们开始动真格的了。很多同学学离线优先架构,第一步就卡在环境搭建上——不是 Gradle 版本对不上,就是依赖冲突搞得头大。我个人习惯是:先让项目跑起来,再逐步填业务逻辑。所以今天咱们就专心搞定 Compose 项目的骨架。
3.1 创建新项目时的版本选择
打开 Android Studio,选 New Project -> Empty Activity。这里有个坑:千万别手快直接点 Finish。Android Studio 默认会用最新稳定版的 AGP(Android Gradle Plugin)和 Kotlin 版本,但这个组合有时候和 Compose BOM 不兼容。我去年有个项目就是被 AGP 8.2 和 Compose 1.5 的隐式依赖坑了一把——编译没问题,一运行就 Crash。
所以我的习惯是:先看一眼官方 Compose 版本兼容表,心里有数再动手。这里给你一张我常用的版本组合参考表:
| 组件 | 推荐版本(2025 Q1) | 说明 |
|---|---|---|
| AGP | 8.3.0 | 太新可能有 bug,太老不支持 Compose 插件 |
| Kotlin | 1.9.22 | 必须和 Compose 编译器版本对应 |
| Compose BOM | 2024.02.02 | 看 BOM 版本就够了,它统一管所有 Compose 库 |
| Compose Compiler | 1.5.10 | 这个版本号必须和 Kotlin 版本精确匹配 |
| Hilt | 2.50 | 离线架构少不了依赖注入 |
| Room | 2.6.1 | 本地持久化核心库 |
创建项目时,我建议你选“Minimum SDK”为 Android 7.0(API 24),别图省事用 API 21,因为 Room 和后台工作在很多老机型上跑不动离线同步逻辑。
3.2 Gradle 配置:从 project 到 module
项目创建完成后,第一件事不是写代码,是打开根目录的 build.gradle.kts(现在都用 Kotlin DSL 了吧?别再用 Groovy 了,维护起来真的头疼)。
// 根目录 build.gradle.kts
plugins {
id("com.android.application") version "8.3.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
id("com.google.dagger.hilt.android") version "2.50" apply false
id("com.google.devtools.ksp") version "1.9.22-1.0.17" apply false
}
然后打开 app/build.gradle.kts,这是重头戏。我一般会分成三块来配置:
- Android 块:设置 compileSdk、minSdk、targetSdk,以及 compose 选项
- 依赖块:用 BOM 统一版本,不手动写单个库版本
- KSP 块:处理 Room annotation processor
来看看我实际项目里的一个最小化配置(可以直接 copy 过去改):
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.dagger.hilt.android")
id("com.google.devtools.ksp")
}
android {
namespace = "com.example.offlinefirst"
compileSdk = 34
defaultConfig {
applicationId = "com.example.offlinefirst"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.10"
}
kotlinOptions {
jvmTarget = "17"
}
}
dependencies {
// Compose BOM —— 所有 Compose 库版本由它统一管理
val composeBom = platform("androidx.compose:compose-bom:2024.02.02")
implementation(composeBom)
// Compose 核心
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.8.2")
// 调试工具(只有 debug 模式才打包)
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
// 离线架构三大件
implementation("androidx.room:room-runtime:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")
ksp("androidx.room:room-compiler:2.6.1") // 用 KSP 替代 kapt,快很多
implementation("com.google.dagger:hilt-android:2.50")
ksp("com.google.dagger:hilt-compiler:2.50")
// 网络(离线优先也要有网络层)
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
// 协程
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}
// 如果 Room schema 需要导出用于数据库迁移
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
3.3 理解这些依赖在离线架构中的角色
你可能会问:就建个空项目,为什么要拉这么多依赖?其实每个库在离线优先架构里都有明确的分工。我画了一张图帮你理清关系:
看明白了吗?从上到下是典型的单向依赖:Compose → ViewModel → Repository → 数据源。而左右两侧的 Room 和 Retrofit 是平级的——离线策略的核心就是让 Repository 决定「优先读哪个、什么时候同步」。WorkManager 则负责在后台乖乖地把待同步数据推上服务器。
3.4 别忘了检查几个关键配置
🔧 三个必须手动确认的点:
- Kotlin 编译器版本:在
composeOptions里写的kotlinCompilerExtensionVersion必须和根目录的 Kotlin 插件版本匹配。我一般都去 官方兼容性表 查完再写。 - KSP 替代 kapt:Room 2.6.0 开始推荐用 KSP,编译速度能快 2-3 倍。记得在
build.gradle.kts里声明id("com.google.devtools.ksp"),然后用ksp()而不是kapt()。 - minSdk 别太低:如果设置成 21,Room 和 Hilt 虽然能工作,但 WorkManager 的延迟初始化在某些低版本上会出诡异问题。我踩过这个坑——最后不得不把 minSdk 提到 24 才解决问题。
💡 我的小技巧:配置完 Gradle 后,先 Sync 一下,然后立刻写一个空的 Compose 页面和一个空的 Room Entity,跑一次构建。如果 2 分钟内能编译通过,恭喜你,后续工作会顺利很多。如果报错,赶紧检查版本号——大部分问题都出在版本不匹配上。
3.5 最后一步:验证项目骨架
为了确保你刚才配置的环境真的能用,我建议你写一个最简单的 Compose 页面测试一下:
// MainActivity.kt
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Text("离线优先架构实战 —— 项目启动成功")
}
}
}
}
如果能在模拟器或者真机上看到这行文字,说明 Compose 环境完全 OK。接下来你就可以放心地往项目里塞 Room、Hilt、WorkManager 了。嗯,到这里项目初始化就算正式完成。你手里的空项目已经搭好了离线优先架构的「地基」——剩下的就是一层层往上盖楼了。