Android 开发
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
app/
├── ui/ # Composables / Activities / Fragments / 屏幕状态
├── presentation/ # ViewModels, UI 状态, UI 事件
├── domain/ # Use cases, 领域模型, 仓库接口
├── data/ # 仓库实现, 远程 (API), 本地 (DB), 映射器 (mappers)
└── di/ # 依赖注入模块数据流 (单向):
用户操作 → 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):
- 使用
Bloc或Cubit隔离业务逻辑
- 使用
AsyncNotifierProvider(Riverpod) 处理数据 + 状态
- 仓库定义为抽象类并注入具体实现
React Native (Redux Toolkit 或 Zustand):
- 使用 RTK Query 或 React Query 处理服务端状态
- 使用 Zustand slices 处理客户端状态
- 使用自定义 Hook 封装每个功能的业务逻辑
KMM:
- 共享的
commonMain包含领域层 + 数据层
- 使用
expect/actual实现平台特定功能
- Kotlin 协程 + Flow 桥接到平台 (Android 端使用 StateFlow)
模块结构 (大型应用采用多模块)
: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
- 副作用仅限在
LaunchedEffect、DisposableEffect、SideEffect中处理
- 避免状态提升反模式:将状态提升至最低公共祖先节点
无障碍访问(强制要求)
- 所有交互元素必须包含
contentDescription或semantics { }
- 最小触摸目标:48×48dp
- 每次发布前必须通过
TalkBack兼容性测试
- 支持动态文本大小(文本使用
sp而非dp)
- 颜色对比度 ≥ 4.5:1 (WCAG AA)
导航
- Native: 使用 Navigation Compose,配合类型安全的
NavHost和SafeArgs等效实现
- 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 class、sealed class、object、enum 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)
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 Crashlytics 或 Sentry
- 在崩溃发生前设置用户标识符和自定义 Key
- 所有捕获的错误均记录为非致命异常 (Non-fatal exceptions)
- 启用 ANR 监控
- 无崩溃会话率目标:≥ 99.5%
离线 / 网络韧性
- 缓存优先策略:显示旧数据,后台异步获取新数据
- 将
Room/Drift/MMKV作为唯一可信源 (Single Source of Truth)
- 通过
ConnectivityManager暴露网络状态并在 UI 中体现
- 所有网络请求均封装超时机制 + 重试策略
---
§6 测试
测试金字塔
/\
/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 构建与发布
构建变体
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 流水线
提交 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 |rememberSaveable
| 旋转后崩溃 | 未使用 ViewModel;状态未保存 | 使用 / ViewModel |derivedStateOf
| UI 卡顿 | 重组循环 (Recomposition loops) | 使用 ,确保参数稳定 |adb shell am start
| API 调用后白屏 | 错误被静默吞掉 | 检查错误状态的传递 |
| Deep link 失效 | Manifest 中缺少 intent-filter | 通过 验证 |
| 推送通知无响应 | 后台限制 | 在不同 OEM 厂商的真机上测试 |
日志标准
- 生产环境: Firebase Crashlytics o
)
- Debug/Staging: 使用带有 debug tree 的 Timber
- 日志级别:ERROR(崩溃)、WARN(可恢复)、INFO(关键事件)、DEBUG(仅限开发)
- 严禁记录 PII(个人可识别信息)—— 对日志中的邮箱、电话号码、Token 进行脱敏处理
OEM 特定问题
- 针对关键流程,在 Samsung、Xiaomi/MIUI、OnePlus/OxygenOS、Huawei (无 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 考量因素