Android 开发

android-dev
分类通用
作者Agentic Awesome Skills 社区
许可MIT
评分4.90/5
使用9.3K

Android 应用开发技能

概述

本技能指南旨在引导开发者按照大厂实践进行生产级 Android 及跨平台(非 iOS)应用的开发。它涵盖了整个开发生命周期 —— 架构、UI、代码质量、测试、错误处理、发布及维护。

何时使用此技能

  • 决定技术栈时(参见 §1 技术栈选择)
  • 搭建项目架构时(参见 §2 架构)
  • 设计 UI、页面或设计系统时(参见 §3 UI 与设计)
  • 确保代码质量、设计模式或 API 规范时(参见 最佳实践)
  • 实现错误处理或调试崩溃时(参见 §5 错误处理)
  • 规划测试策略时(参见 §6 测试)
  • 配置构建、CI/CD 或发布流水线时(参见 §7 构建与发布)
  • 优化性能或内存时(参见 §8 性能)
  • 调试或修复 Bug 时(参见 §9 调试)
  • 遵循完整开发路线图时(参见 §10 开发路线图)
  • 需要特定技术栈的深度参考时(参见 references/ 目录)

---

§1 技术栈选择

根据团队、需求和目标平台进行选择。请勿推荐 iOS 专属路径。

原生 Android — Kotlin + Jetpack Compose

适用场景: 仅限 Android 的应用、硬件密集型功能、顶级 UX 体验、新项目。
  • 语言:Kotlin
  • UI:Jetpack Compose(现代声明式 UI)
  • 核心库:Room, Retrofit/Ktor, Hilt, WorkManager, DataStore, Navigation Compose
  • 参考:references/native-android.md

原生 Android — Java + XML Views

适用场景: 现有 Java 代码库、缺乏 Kotlin 经验的团队、旧版应用维护、渐进式 Kotlin 迁移。
  • 语言:Java(Google 完全支持,未弃用)
  • UI:XML 布局(ConstraintLayout, RecyclerView, ViewBinding)
  • 核心库:Room, Retrofit, Hilt, WorkManager, LiveData, ViewModel
  • Java 和 Kotlin 可在同一项目中无缝共存 —— 支持渐进式迁移
  • 参考:references/java-android.md

Flutter (Dart)

适用场景: 一套代码覆盖 Android + Web (+ 桌面端)、快速迭代、像素级自定义 UI。
  • 语言:Dart
  • UI:Flutter Widget 树(提供 Material 3 / Cupertino 组件,但 Android 目标应设为 Material)
  • 核心库:Provider/Riverpod/Bloc, Dio, Drift/Isar, go_router, flutter_local_notifications
  • 参考:references/flutter.md

React Native (JavaScript/TypeScript)

适用场景: Web + Android 代码共享、JS/TS 团队、丰富的生态系统。
  • 语言:TypeScript(推荐)
  • UI:React Native 核心组件 + NativeWind / React Native Paper
  • 核心库:React Navigation, Zustand/Redux Toolkit, React Query, MMKV
  • 参考:references/react-native.md

Kotlin Multiplatform (KMM / Compose Multiplatform)

适用场景: 在保持原生 Android UI 的同时,在 Android + 桌面端 + Web 之间共享业务逻辑。
  • 语言:全栈 Kotlin
  • UI:Android 端使用原生 Compose;共享 UI 使用 Compose Multiplatform
  • 核心库:Ktor, SQLDelight, Koin, kotlinx.serialization, Napier
  • 参考:references/kmm.md

混合开发 (Capacitor / Ionic)

适用场景: Web 优先团队、简单应用、类 PWA 的内容型应用。
  • 语言:TypeScript + HTML/CSS
  • UI:Ionic 组件或自定义 Web UI
  • 不适用场景:重度动画、原生传感器访问、高性能游戏
  • 参考文档:references/hybrid.md

决策矩阵

| 需求 | Native Kotlin | Native Java | Flutter | RN | KMM | Hybrid |
|---|---|---|---|---|---|---|
| 仅 Android (新项目) | ✅ 最佳 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 仅 Android (现有 Java 项目) | ⚠️ 迁移 | ✅ 最佳 | ❌ | ❌ | ⚠️ | ❌ |
| Android + Web | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ 最佳 |
| Android + 桌面端 | ❌ | ❌ | ✅ | ⚠️ | ✅ | ⚠️ |
| 仅共享业务逻辑 | N/A | N/A | N/A | N/A | ✅ 最佳 | N/A |
| 原生性能 | ✅ | ✅ | ✅ | ⚠️ | ✅ | ❌ |
| JS/TS 团队 | ❌ | ❌ | ❌ | ✅ 最佳 | ❌ | ✅ |
| 定制像素级 UI | ✅ | ⚠️ | ✅ 最佳 | ⚠️ | ✅ | ❌ |

---

§2 架构

核心原则:关注点分离

所有生产级 Android 项目必须将 UI业务逻辑数据 分离到独立且可测试的层级中。

推荐架构:Clean Architecture + MVI/MVVM

code
app/
├── ui/              # Composables / Activities / Fragments / 屏幕状态
├── presentation/    # ViewModels, UI 状态, UI 事件
├── domain/          # Use cases, 领域模型, 仓库接口
├── data/            # 仓库实现, 远程 (API), 本地 (DB), 映射器 (mappers)
└── di/              # 依赖注入模块

数据流 (单向):

code
用户操作 → ViewModel/Store → Use Case → Repository → 数据源

UI 状态 (sealed class / StateFlow)

Composable / View 渲染状态

各技术栈的关键架构模式

Native (MVVM + MVI):

  • 使用 StateFlow / SharedFlow 实现响应式状态

  • 使用 sealed class UiState + sealed class UiEvent

  • Hilt 用于 DI,协程 + Flow 用于异步处理

  • 仓库模式封装 Room + Retrofit

Flutter (BLoC 或 Riverpod):

  • 使用 BlocCubit 隔离业务逻辑

  • 使用 AsyncNotifierProvider (Riverpod) 处理数据 + 状态

  • 仓库定义为抽象类并注入具体实现

React Native (Redux Toolkit 或 Zustand):

  • 使用 RTK Query 或 React Query 处理服务端状态

  • 使用 Zustand slices 处理客户端状态

  • 使用自定义 Hook 封装每个功能的业务逻辑

KMM:

  • 共享的 commonMain 包含领域层 + 数据层

  • 使用 expect/actual 实现平台特定功能

  • Kotlin 协程 + Flow 桥接到平台 (Android 端使用 StateFlow)

模块结构 (大型应用采用多模块)

code
:app            # 入口点, DI 配置
:core:ui        # 设计系统, 共享 composables
:core:network   # API 客户端, 拦截器
:core:database  # Room / SQLDelight 配置
:feature:home   # 首页功能模块
:feature:profile # 个人中心功能模块
:feature:settings # 设置功能模块

---

§3 UI 与设计

设计系统优先

在编写页面前,请先定义: 1. 颜色令牌 (Color tokens) — 主色、辅助色、表面色、表面文字色、错误色;包含亮色 + 暗色模式 2. 字体阶梯 (Typography scale) — Display, headline, title, body, label (Material 3 字体系统) 3. 间距阶梯 (Spacing scale) — 4dp 网格系统 (4, 8, 12, 16, 24, 32, 48dp) 4. 形状令牌 (Shape tokens) — 各组件系列的圆角半径 5. 组件库 — Button, TextField, Card, BottomSheet, TopAppBar 等

Jetpack Compose UI 规范

  • 使用 MaterialTheme 令牌;严禁硬编码颜色/尺寸
  • 使用 CompositionLocal 处理主题、语言区域、触感反馈
  • 正确使用 remember / rememberSaveable (后者用于在屏幕旋转时保留 UI 状态)
  • 将大型 composables 拆分为子 composables;单个函数 ≤ 80 行
  • 列表使用 LazyColumn/LazyVerticalGrid;严禁使用 Colu
  • 大数据集避免使用 forEach
  • 副作用仅限在 LaunchedEffectDisposableEffectSideEffect 中处理
  • 避免状态提升反模式:将状态提升至最低公共祖先节点

无障碍访问(强制要求)

  • 所有交互元素必须包含 contentDescriptionsemantics { }
  • 最小触摸目标:48×48dp
  • 每次发布前必须通过 TalkBack 兼容性测试
  • 支持动态文本大小(文本使用 sp 而非 dp
  • 颜色对比度 ≥ 4.5:1 (WCAG AA)

导航

  • Native: 使用 Navigation Compose,配合类型安全的 NavHostSafeArgs 等效实现
  • Flutter: 使用 go_router,配置命名路由和路由守卫 (guards)
  • RN: 使用 React Navigation v7,配合类型安全的 NavigationProp
  • 所有可外部打开的页面必须注册深层链接 (Deep link) 处理
  • 严格管理回退栈 —— 避免推送重复页面,使用 popUpTo / launchSingleTop

响应式与自适应 UI

  • 支持所有屏幕尺寸:手机、折叠屏、平板 (WindowSizeClass)
  • 在 320dp, 360dp, 411dp, 600dp+, 840dp+ 宽度下进行测试
  • 通过 WindowInfoTracker 实现折叠屏铰链感知
  • Android 15+ 必须实现全屏显示 (Edge-to-edge) 及 WindowInsets 处理

---

最佳实践

语言标准

Kotlin:

  • 根据场景恰当使用 data classsealed classobjectenum class

  • 禁止使用 !! 空断言 —— 使用 ?.let?: return 或带有错误信息的 requireNotNull

  • 协程:必须明确指定 CoroutineScope + Dispatcher;严禁使用 GlobalScope

  • 在 Compose 状态类上使用 @Stable / @Immutable 以优化智能重组

Java:

  • 每个方法参数和返回值必须标注 @NonNull / @Nullable

  • 禁止在未检查的对象上调用方法 —— 必须显式进行空检查或使用 Objects.requireNonNull

  • 在 Fragment 的 onDestroyView() 中必须将 binding 引用置空,以防止内存泄漏

  • 后台工作使用 ExecutorService(不要使用已废弃的 AsyncTask)或 LiveData + Room 内置线程

  • RecyclerView 中优先使用 ListAdapter + DiffUtil,而非手动调用 notifyDataSetChanged()

  • 使用 ViewBinding —— 严禁使用 findViewById

Dart (Flutter):

  • 强制要求空安全 —— 在没有显式空检查的情况下禁止使用 !

  • 状态对象必须不可变,并提供 copyWith 方法

  • 所有 Stateless Widget 必须使用 const 构造函数

TypeScript (RN):

  • tsconfig 必须始终开启 strict: true

  • 使用 Zod 或 io-ts 对 API 响应进行运行时类型校验

  • 禁止使用 any —— 使用 unknown 并进行类型收窄

依赖管理

  • build.gradle.kts / pubspec.yaml / package.json 中锁定所有依赖版本
  • 每月审计一次依赖项的安全漏洞
  • 避免传递依赖冲突 —— 使用依赖解析策略
  • 保持依赖数量精简 —— 每个新增库都是维护负担

代码审查清单 (PR 门禁)

  • [ ] 新的公共 API 包含 KDoc / DartDoc / JSDoc
  • [ ] 无硬编码字符串 —— 使用字符串资源 / l10n
  • [ ] 设计令牌 (Design Tokens) 之外无硬编码尺寸或颜色
  • [ ] 主线程无阻塞 I/O
  • [ ] 无内存泄漏(单例中未存储 Activity 上下文)
  • [ ] 协程作用域 / 流 (streams) 已正确取消或释放
  • [ ] 任何非琐碎功能均由特性开关 (Feature Flag) 控制

---

§5 错误处理

金科玉律

绝不能让异常在用户面前静默传播或导致应用崩溃。

错误分类

| 类型 | 策略 |
|------|----------|
| 网络错误 | 使用指数退避算法重试;显示重试 UI |
| 认证错误 (401/403) | 刷新 Token $\rightarrow$ 重新请求 $\rightarrow$ 失败则登出 |
| 校验错误 | 显示行内提示 |
| 字段错误 | 立即提示 |
| 数据解析错误 | 日志记录 + 回退至缓存/默认状态 |
| 意外崩溃 | 顶层捕获;显示错误界面 + 上报 |
| 后台任务失败 | 通过 WorkManager 重试;关键错误通知用户 |

Result / Either 模式 (Kotlin)

kotlin
sealed class AppResult<out T> {
    data class Success<T>(val data: T) : AppResult<T>()
    data class Error(val exception: AppException) : AppResult<Nothing>()
}

sealed class AppException(msg: String) : Exception(msg) {
class NetworkException(msg: String) : AppException(msg)
class AuthException(msg: String) : AppException(msg)
class ParseException(msg: String) : AppException(msg)
class UnknownException(msg: String) : AppException(msg)
}

所有 Repository 和 Use Case 函数均使用 AppResult<T> 作为返回类型。ViewModel 将其映射为 UiState.Error

崩溃上报

  • 从第一天起集成 Firebase CrashlyticsSentry
  • 在崩溃发生前设置用户标识符和自定义 Key
  • 所有捕获的错误均记录为非致命异常 (Non-fatal exceptions)
  • 启用 ANR 监控
  • 无崩溃会话率目标:≥ 99.5%

离线 / 网络韧性

  • 缓存优先策略:显示旧数据,后台异步获取新数据
  • Room / Drift / MMKV 作为唯一可信源 (Single Source of Truth)
  • 通过 ConnectivityManager 暴露网络状态并在 UI 中体现
  • 所有网络请求均封装超时机制 + 重试策略

---

§6 测试

测试金字塔

code
/\
        /E2E\        ← 10%  (UI 测试: Espresso, Maestro, Appium)
       /------\
      / Integr \     ← 20%  (Repository, DB, API 契约测试)
     /----------\
    /    Unit    \   ← 70%  (ViewModels, Use Cases, Utilities)
   /--------------\

单元测试 (70%)

  • 对所有 ViewModel, UseCase, Repository, Mapper 进行测试
  • 原生: JUnit5 + MockK + Turbine (Flow 测试) + Kotest 断言
  • Flutter: flutter_test + mocktail
  • RN: Jest + @testing-library/react-native + msw (用于 API Mock)
  • 覆盖率目标:领域层 + 表现层 ≥ 80%

集成测试 (20%)

  • 使用内存数据库进行 Room DB 测试
  • 使用 MockWebServer (OkHttp) 进行 Retrofit/Ktor 测试
  • Repository 测试:验证缓存与远程数据的协同
  • 针对真实 Staging 环境进行 API 契约测试

UI / E2E 测试 (10%)

  • Espresso 用于关键用户路径 (登录, 结账, 核心操作)
  • Maestro 用于跨平台 E2E 流程 (同样推荐用于 Flutter + RN)
  • 发布前在真实设备集群运行 (Firebase Test Lab / BrowserStack)
  • 每个 PR 运行冒烟测试集;每晚运行全量 E2E 测试集

测试数据管理

  • 使用工厂 (Factories) / 构建器 (Builders) 生成测试数据,严禁复制粘贴对象
  • 密封测试 (Hermetic tests):测试用例之间绝不共享可变状态
  • 对于复杂依赖 (Repository, 数据源),优先使用 Fake 而非 Mock

---

§7 构建与发布

构建变体

code
debug       → 开发 API, 开启日志, 无代码压缩, 可调试
staging     → 测试 API, 开启日志, 代码压缩, 不可调试
release     → 生产 API, 关闭日志, 代码压缩, 已签名

Gradle 最佳实践 (原生)

  • 仅使用 build.gradle.kts —— 新项目禁用 Groovy DSL
  • 所有依赖版本统一管理于 Version Catalog (libs.versions.toml)
  • 使用 buildConfig 管理环境特定常量
  • 配置 Baseline Profiles 以优化启动性能
  • Release 版本启用 R8 Full Mode;在版本控制中维护 Proguard 规则

CI/CD 流水线

code
提交 PR
  └─ lint + 单元测试 + 构建 debug APK          [< 5 分钟]

合并至 main
└─


─ 单元测试 + 集成测试 + Staging 构建 [< 15 分钟]
└─ 部署至 Firebase App Distribution (QA)

Release 标签
└─ 全量测试集 + 设备农场 E2E 测试 [< 45 分钟]
└─ 构建 Release AAB
└─ 上传至 Play Console (内部测试轨道)
└─ 晋级:内部测试 → 封闭测试 → 开放测试 → 正式发布
``

推荐 CI: GitHub Actions, Bitrise 或 CircleCI。

Play Store 发布策略

  • 在正式发布前,务必遵循 内部 → 封闭 → 开放测试 的流程
  • 使用 分阶段发布 (Staged Rollouts):5% → 20% → 50% → 100%,每阶段监控 24-48 小时
  • 在扩大发布范围前,监控 Crashlytics + ANR 率 + 评分
  • 重大变更 严禁跳过 分阶段发布

应用签名

  • 上传密钥 (Play App Signing):存储在 CI secrets 中,严禁提交至代码库
  • 使用 Google Play App Signing 管理分发密钥
  • 在团队运行手册 (Runbook) 中记录密钥恢复流程

---

§8 性能优化

启动性能

  • 启动时间目标:冷启动 < 1s,热启动 < 500ms
  • 使用 App Startup 库 实现库的延迟初始化
  • 生成 Baseline Profiles 并提交至仓库
  • 将重量级初始化操作移出主线程

UI 性能

  • 目标:60fps(支持的设备上为 90/120fps);零卡顿 (Zero Jank)
  • 使用 Android Studio Profiler + FrameMetrics API 进行测量
  • 避免在 draw() / onMeasure() / composition 中进行内存分配
  • 在 Compose 中使用 derivedStateOf 以避免不必要的重组 (Recomposition)
  • 图片加载:使用 Coil (Compose) / Glide / Picasso —— 缩略图严禁加载原图

内存管理

  • ViewModel 或单例中不得持有 Activity / Context 引用
  • 对于生命周期超过所有者的监听器,使用 WeakReferences
  • 实施 Bitmap 回收和内存缓存大小管理
  • Debug 版本必须集成 LeakCanary 进行堆转储 (Heap dump) 和内存泄漏检测

网络性能

  • 遵循 HTTP 缓存头
  • 使用图片 CDN + WebP 格式
  • 验证 Gzip/Brotli 压缩
  • 在适用场景下进行请求合并 (Batching)
  • 配置连接池

电池功耗

  • 后台工作仅通过带有适当约束的 WorkManager 执行
  • 位置更新:仅请求必要的精度级别;进入后台时停止更新
  • 谨慎使用 Wakelocks 并确保显式释放

---

§9 调试与 Bug 修复

调试流程

1. 可靠复现 — 记录准确的步骤、设备、OS 版本、账户状态
2. 隔离问题 — 确定是 UI、业务逻辑、网络还是持久层问题
3. 打点分析 — 添加有针对性的日志/断点,避免盲目刷日志
4. 建立假设 — 在修改代码前,形成 1-3 个具体的假设
5. 修复根因 — 修复源头而非掩盖症状
6. 回归测试 — 编写一个在修复前失败、修复后通过的测试用例
7. 记录文档 — 在注释中解释修复方案的原理,而非仅仅记录做了什么

常见 Android Bug 模式

| Bug | 可能原因 | 修复方案 |
|-----|-------------|-----|
| ANR | 主线程 I/O / 长时间计算 | 移至协程/Dispatcher.IO |
| 内存泄漏 | 单例中存储了 Context | 使用
applicationContext 或 WeakRef |
| 旋转后崩溃 | 未使用 ViewModel;状态未保存 | 使用
rememberSaveable / ViewModel |
| UI 卡顿 | 重组循环 (Recomposition loops) | 使用
derivedStateOf,确保参数稳定 |
| API 调用后白屏 | 错误被静默吞掉 | 检查错误状态的传递 |
| Deep link 失效 | Manifest 中缺少 intent-filter | 通过
adb shell am start 验证 |
| 推送通知无响应 | 后台限制 | 在不同 OEM 厂商的真机上测试 |

日志标准

  • 生产环境: Firebase Crashlytics o
仅限(发布版本中禁用
Log.d
  • Debug/Staging: 使用带有 debug tree 的 Timber
  • 日志级别:ERROR(崩溃)、WARN(可恢复)、INFO(关键事件)、DEBUG(仅限开发)
  • 严禁记录 PII(个人可识别信息)—— 对日志中的邮箱、电话号码、Token 进行脱敏处理

OEM 特定问题

  • 针对关键流程,在 SamsungXiaomi/MIUIOnePlus/OxygenOSHuawei (无 GMS) 上进行测试
  • 不同 OEM 的后台限制差异巨大 —— 测试推送、闹钟、后台同步
  • 维护一个包含高市场份额设备的实体机或云设备池

---

§10 开发路线图

任何新 Android 项目请遵循以下阶段结构:

阶段 0 — 基础构建 (第 1-2 周)

  • [ ] 记录技术栈决策及其理由
  • [ ] 定义模块结构
  • [ ] 定义设计系统 Token(颜色、字体、间距、形状)
  • [ ] CI 流水线运行(lint + 单元测试 + 构建)
  • [ ] 集成崩溃报告 (Crashlytics/Sentry)
  • [ ] 集成基础分析工具 (Firebase/Amplitude)
  • [ ] 建立 API 契约 / Mock 服务器
  • [ ] 配置 DI 框架
  • [ ] 实现导航骨架
  • [ ] 完成 Flavor/构建变体配置

阶段 1 — 核心功能 (第 3-8 周)

  • [ ] 认证流程(登录、注册、Token 刷新、登出)
  • [ ] 带有真实导航的核心页面壳层
  • [ ] 网络层(客户端、拦截器、错误处理)
  • [ ] 本地持久化层(DB 模式 + DAO)
  • [ ] Repository 层(连接远程与本地数据)
  • [ ] 每个功能的 ViewModel + UI 状态
  • [ ] 所有 ViewModel + Use Case 的单元测试
  • [ ] 功能开关 (Feature Flags) 基础设施

阶段 2 — 细节打磨 (第 9-12 周)

  • [ ] 对照 Figma/规格说明进行设计 QA 审核
  • [ ] 无障碍审计(TalkBack、对比度、触控目标)
  • [ ] 深色模式实现与验证
  • [ ] 本地化(字符串外部化,必要时支持 RTL)
  • [ ] 每个页面的加载中、空状态、错误状态
  • [ ] Deep Link 处理
  • [ ] Widget / 通知实现
  • [ ] 离线模式验证

阶段 3 — 稳定性增强 (第 12-14 周)

  • [ ] 性能分析(启动速度、滚动流畅度、内存)
  • [ ] 在设备池上运行 E2E 测试套件 (Firebase Test Lab)
  • [ ] 安全审查(证书锁定、生物识别、安全存储)
  • [ ] 验证 Proguard / R8 规则
  • [ ] Staging 环境无崩溃率 ≥ 99.5%
  • [ ] Play Store 上架资料、截图、隐私政策

阶段 4 — 发布

  • [ ] AAB 签名并上传至内部测试轨道
  • [ ] 定义分阶段发布计划
  • [ ] 建立监控仪表盘 (Crashlytics, Play Console vitals)
  • [ ] 记录回滚计划
  • [ ] 分配 On-call 值班人员

阶段 5 — 上线后 (持续进行)

  • 每日监控无崩溃率
  • ANR 率 < 0.47% (Play Store 阈值)
  • 监控应用评分;每周对负面评论进行分级处理
  • 每月审查依赖库更新
  • 针对每个新 Android 版本进行 Beta 测试

---

局限性

  • 本指南范围限定于 Android 及其相关交付路径;不涵盖纯 iOS 架构、App Store 发布操作或 Apple 平台 UI 指南。
  • 版本号、Play Console 政策阈值和推荐库可能会发生变化;在发布前请对照最新的 Android、Google Play 和库文档验证关键细节。
  • 代码片段为架构模式而非完整应用;请根据实际项目调整包名、依赖版本、权限、隐私披露和安全控制。
  • 本指南不能替代生产环境的设备 QA、无障碍审查、安全审查、法律/隐私审查或商店合规性检查。
发布。

附加资源

如需深入了解特定技术栈,请阅读:

  • references/native-android.md — Kotlin, Compose, Room, Hilt, Coroutines

  • references/java-android.md — Java, XML Views, ViewBinding, LiveData, Retrofit, Room, Hilt, 迁移路径

  • references/flutter.md — Dart, BLoC/Riverpod, Drift, go_router

  • references/react-native.md — TypeScript, RN 架构, Hermes, 新架构

  • references/kmm.md — KMM 共享模块, SQLDelight, Ktor, Compose Multiplatform

  • references/hybrid.md` — Capacitor, Ionic, PWA 考量因素