SKILL.md
只读
名称
android-native-dev
描述
Android 原生应用开发与 UI 设计指南。涵盖 Material Design 3、Kotlin/Compose 开发、项目配置、无障碍功能以及构建排错等内容。进行 Android 原生应用开发前请先阅读本指南。
1. 项目场景评估
在开始开发之前,先评估当前项目的状态:
| 场景 | 特征 | 处置方式 |
|---|---|---|
| 空目录 | 不存在任何文件 | 需要进行完整初始化,包括 Gradle Wrapper |
| 已包含 Gradle Wrapper | 存在 gradlew 和 gradle/wrapper/ |
直接使用 ./gradlew 进行构建 |
| Android Studio 项目 | 包含完整的项目结构,但可能缺少 Wrapper | 检查 Wrapper,必要时运行 gradle wrapper |
| 残缺项目 | 仅存在部分文件 | 检查缺失文件并补全配置 |
核心原则:
- 在编写业务逻辑之前,务必确保
./gradlew assembleDebug能够顺利构建成功 - 如果缺少
gradle.properties,请先创建该文件并配置 AndroidX
1.1 必备文件清单
MyApp/
├── gradle.properties # 配置 AndroidX 及其他设置
├── settings.gradle.kts
├── build.gradle.kts # 根目录级
├── gradle/wrapper/
│ └── gradle-wrapper.properties
├── app/
│ ├── build.gradle.kts # 模块级
│ └── src/main/
│ ├── AndroidManifest.xml
│ ├── java/com/example/myapp/
│ │ └── MainActivity.kt
│ └── res/
│ ├── values/
│ │ ├── strings.xml
│ │ ├── colors.xml
│ │ └── themes.xml
│ └── mipmap-*/ # 应用图标
2. 项目配置
2.1 gradle.properties
# 必需配置
android.useAndroidX=true
android.enableJetifier=true
# 构建优化
org.gradle.parallel=true
kotlin.code.style=official
# JVM 内存设置(根据项目规模调整)
# 小型项目:2048m,中型项目:4096m,大型项目:8192m+
# org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
注意:如果构建过程中遇到
OutOfMemoryError,请加大-Xmx的值。依赖项较多的大型项目可能需要 8GB 或更高的内存。
2.2 依赖声明规范
dependencies {
// 使用 BOM 统一管理 Compose 版本
implementation(platform("androidx.compose:compose-bom:2024.02.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
// Activity 与 ViewModel
implementation("androidx.activity:activity-compose:1.8.2")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
}
2.3 构建变体(Build Variants)与 Product Flavors
Product Flavors 允许你为应用构建不同的版本(例如:免费版/付费版、开发环境/预发布环境/生产环境)。
app/build.gradle.kts 配置示例:
android {
// 定义 Flavor 维度
flavorDimensions += "environment"
productFlavors {
create("dev") {
dimension = "environment"
applicationIdSuffix = ".dev"
versionNameSuffix = "-dev"
// 为不同 Flavor 配置专属变量
buildConfigField("String", "API_BASE_URL", "\"https://dev-api.example.com\"")
buildConfigField("Boolean", "ENABLE_LOGGING", "true")
// 为不同 Flavor 配置专属资源
resValue("string", "app_name", "MyApp Dev")
}
create("staging") {
dimension = "environment"
applicationIdSuffix = ".staging"
versionNameSuffix = "-staging"
buildConfigField("String", "API_BASE_URL", "\"https://staging-api.example.com\"")
buildConfigField("Boolean", "ENABLE_LOGGING", "true")
resValue("string", "app_name", "MyApp Staging")
}
create("prod") {
dimension = "environment"
// 生产环境不添加后缀
buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"")
buildConfigField("Boolean", "ENABLE_LOGGING", "false")
resValue("string", "app_name", "MyApp")
}
}
buildTypes {
debug {
isDebuggable = true
isMinifyEnabled = false
}
release {
isDebuggable = false
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
}
Build Variant 命名规则:{flavor}{BuildType} → 例如 devDebug、prodRelease
Gradle 构建命令:
# 列出所有可用的构建变体
./gradlew tasks --group="build"
# 构建特定的变体(flavor + buildType)
./gradlew assembleDevDebug # Dev 环境,Debug 构建
./gradlew assembleStagingDebug # Staging 环境,Debug 构建
./gradlew assembleProdRelease # Prod 环境,Release 构建
# 构建指定 flavor 的所有变体
./gradlew assembleDev # Dev 的所有变体(debug + release)
./gradlew assembleProd # Prod 的所有变体
# 构建指定 buildType 的所有变体
./gradlew assembleDebug # 所有 flavor 的 Debug 构建
./gradlew assembleRelease # 所有 flavor 的 Release 构建
# 将特定变体安装至设备
./gradlew installDevDebug
./gradlew installProdRelease
# 构建并安装(一步到位)
./gradlew installDevDebug && adb shell am start -n com.example.myapp.dev/.MainActivity
在代码中读取 BuildConfig:
注意:从 AGP 8.0 开始,默认不再自动生成
BuildConfig。必须在build.gradle.kts中显式开启:android { buildFeatures { buildConfig = true } }
// 在代码中使用构建配置值
val apiUrl = BuildConfig.API_BASE_URL
val isLoggingEnabled = BuildConfig.ENABLE_LOGGING
if (BuildConfig.DEBUG) {
// 仅在 Debug 模式下执行的代码
}
Flavor 专属源码集(Source Sets):
app/src/
├── main/ # 所有 Flavor 共享的代码
├── dev/ # Dev 专属的代码与资源
│ ├── java/
│ └── res/
├── staging/ # Staging 专属的代码与资源
├── prod/ # Prod 专属的代码与资源
├── debug/ # Debug 构建类型专属代码
└── release/ # Release 构建类型专属代码
多维 Flavor 维度(例如:环境 + 版本类型):
android {
flavorDimensions += listOf("environment", "tier")
productFlavors {
create("dev") { dimension = "environment" }
create("prod") { dimension = "environment" }
create("free") { dimension = "tier" }
create("paid") { dimension = "tier" }
}
}
// 生成的变体包含:devFreeDebug、devPaidDebug、prodFreeRelease 等
3. Kotlin 开发规范
3.1 命名约定
| 类型 | 命名规范 | 示例 |
|---|---|---|
| 类 / 接口 | 大驼峰(PascalCase) | UserRepository, MainActivity |
| 函数 / 变量 | 小驼峰(camelCase) | getUserName(), isLoading |
| 常量 | 全大写蛇形(SCREAMING_SNAKE) | MAX_RETRY_COUNT |
| 包名 | 全小写(lowercase) | com.example.myapp |
| Composable 组件 | 大驼峰(PascalCase) | @Composable fun UserCard() |
3.2 代码编码规范(重点)
空安全:
// ❌ 避免使用:非空强转 !!(容易导致 Crash)
val name = user!!.name
// ✅ 推荐使用:安全调用 + 默认值
val name = user?.name ?: "Unknown"
// ✅ 推荐使用:let 作用域函数处理
user?.let { processUser(it) }
异常处理:
// ❌ 避免使用:业务层盲目 try-catch 吞掉异常
fun loadData() {
try {
val data = api.fetch()
} catch (e: Exception) {
// 吞掉异常,极难排查问题
}
}
// ✅ 推荐使用:让异常向上抛出,在合适的层级统一处理
suspend fun loadData(): Result<Data> {
return try {
Result.success(api.fetch())
} catch (e: Exception) {
Result.failure(e) // 包装并返回,由调用方决定如何处理
}
}
// ✅ 推荐使用:ViewModel 中统一处理
viewModelScope.launch {
runCatching { repository.loadData() }
.onSuccess { _uiState.value = UiState.Success(it) }
.onFailure { _uiState.value = UiState.Error(it.message) }
}
3.3 线程与协程(关键)
线程调度选择原则:
| 操作类型 | 线程/调度器 | 说明 |
|---|---|---|
| UI 更新 | Dispatchers.Main |
更新 View、State、LiveData |
| 网络请求 | Dispatchers.IO |
HTTP 调用、API 请求 |
| 文件 I/O | Dispatchers.IO |
本地存储、数据库操作 |
| 计算密集型 | Dispatchers.Default |
JSON 解析、数据排序、加解密 |
正确用法示例:
// 在 ViewModel 中
viewModelScope.launch {
// 默认在主线程,可更新 UI State
_uiState.value = UiState.Loading
// 切换至 IO 线程发起网络请求
val result = withContext(Dispatchers.IO) {
repository.fetchData()
}
// 自动切回主线程,更新 UI
_uiState.value = UiState.Success(result)
}
// 在 Repository 中(suspend 函数应具备 main-safe 特性)
suspend fun fetchData(): Data = withContext(Dispatchers.IO) {
api.getData()
}
常见错误模式:
// ❌ 错误:在 IO 线程直接更新 UI
viewModelScope.launch(Dispatchers.IO) {
val data = api.fetch()
_uiState.value = data // 触发 Crash 或警告!
}
// ❌ 错误:在主线程执行耗时操作
viewModelScope.launch {
val data = api.fetch() // 阻塞主线程!可能导致 ANR
}
// ✅ 正确:IO 线程获取数据,主线程更新状态
viewModelScope.launch {
val data = withContext(Dispatchers.IO) { api.fetch() }
_uiState.value = data
}
3.4 可见性修饰符规范
// 默认修饰符为 public,按需显式声明
class UserRepository { // public
private val cache = mutableMapOf<String, User>() // 仅类内部可见
internal fun clearCache() {} // 仅模块内部可见
}
// data class 属性默认是 public,跨模块使用时请格外注意
data class User(
val id: String, // public
val name: String
)
3.5 常见语法陷阱
// ❌ 错误:直接访问未初始化的 lateinit 变量
class MyViewModel : ViewModel() {
lateinit var data: String
fun process() = data.length // 可能引发 Crash
}
// ✅ 正确:使用可空类型或提供默认值
class MyViewModel : ViewModel() {
var data: String? = null
fun process() = data?.length ?: 0
}
// ❌ 错误:在 lambda 中直接使用 return
list.forEach { item ->
if (item.isEmpty()) return // 会直接从外层函数返回!
}
// ✅ 正确:使用 return@forEach
list.forEach { item ->
if (item.isEmpty()) return@forEach
}
3.6 服务端返回的 Data Class 属性必须设为可空
// ❌ 错误:属性声明为非空(服务端可能返回 null 或缺省)
data class UserResponse(
val id: String = "",
val name: String = "",
val avatar: String = ""
)
// ✅ 正确:所有属性均显式声明为可空类型
data class UserResponse(
@SerializedName("id")
val id: String? = null,
@SerializedName("name")
val name: String? = null,
@SerializedName("avatar")
val avatar: String? = null
)
3.7 生命周期与资源管理
// ❌ 错误:只添加 Observer 但未移除
class MyView : View {
override fun onAttachedToWindow() {
super.onAttachedToWindow()
activity?.lifecycle?.addObserver(this)
}
// 内存泄漏!
}
// ✅ 正确:配对添加与移除
class MyView : View {
override fun onAttachedToWindow() {
super.onAttachedToWindow()
activity?.lifecycle?.addObserver(this)
}
override fun onDetache
<!-- truncated for translation batch; full body continues in source -->






