android-native-dev

android-native-dev

热门

Android 原生应用开发与 UI 设计指南。涵盖 Material Design 3、Kotlin/Compose 开发、项目配置、无障碍功能以及构建排错等内容。进行 Android 原生应用开发前请先阅读本指南。

1.3万Star
1131Fork
更新于 2026/4/18
SKILL.md
只读
名称
android-native-dev
描述

Android 原生应用开发与 UI 设计指南。涵盖 Material Design 3、Kotlin/Compose 开发、项目配置、无障碍功能以及构建排错等内容。进行 Android 原生应用开发前请先阅读本指南。

1. 项目场景评估

在开始开发之前,先评估当前项目的状态:

场景 特征 处置方式
空目录 不存在任何文件 需要进行完整初始化,包括 Gradle Wrapper
已包含 Gradle Wrapper 存在 gradlewgradle/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} → 例如 devDebugprodRelease

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 -->