Skip to content

应用架构设计实战(新应用从 0 到 1 + 通用模块封装)

资深架构师视角的应用工程笔记。覆盖:新应用架构决策路径、分层/组件化/路由、跨端架构、网络/登录/图片/存储/日志/路由/埋点/推送/崩溃/UI/权限/性能/配置/安全 等模块的封装范式。面向工程落地,不做概念科普


目录


一、架构决策方法论

1.1 三层目标

层次目标衡量
业务架构业务域划分、流程编排用例覆盖度、领域边界
应用架构分层、模块化、依赖规则编译依赖图、模块耦合度
技术架构框架选型、基建性能、稳定性、可维护性指标

1.2 决策原则

  • YAGNI:不提前设计未发生的需求。
  • KISS:能用一层不要两层;能用结构体不要类。
  • 依赖倒置:业务定义协议,基建实现协议;业务永远不直接依赖底层 SDK。
  • 单向依赖:上层 → 下层;禁止反向。
  • 稳定依赖:稳定点(协议、领域模型)依赖不稳定点(实现)。
  • 隔离变化:把会变的(业务策略、UI、网络栈)和不变的(领域模型、协议)分离。

1.3 常见反模式

反模式表现纠正
Fat Controller/Activity/VC一个类 3000 行拆 Service + ViewModel
上帝对象全局 Manager 什么都能做拆领域 Service
滥用单例状态隐式耦合DI 注入
基建反向依赖业务网络库引用业务 Model反转,用泛型 + 协议
过早抽象一个调用点就抽 4 层三次重复再抽象
链式回调地狱Promise 嵌套 5 层async/await / Flow / Combine
配置即代码硬编码 everywhere抽 ConfigCenter

二、新应用从 0 到 1 架构路径

2.1 阶段决策树

需求 → 团队规模 →
    单团队小项目 → 单 Module 分包
    多团队/多业务线 → 组件化(多 Pod/Module/Package)
→ 端选择 →
    单端 → 原生(iOS Swift / Android Kotlin)
    双端 → Flutter(首选)/ RN(互动少)/ KMP(重逻辑)
    三端(含 Web) → Flutter Web(短页面)/ React(重交互)
→ 复杂度评估 →
    简单 CRUD → MVVM + Repository
    状态机复杂(IM、播放器、订单)→ MVI / Redux / Bloc
    富领域(电商、金融)→ Clean Architecture + DDD 简化版

2.2 技术选型矩阵

维度iOSAndroidFlutter
语言Swift 5.9+Kotlin 1.9+Dart 3+
UISwiftUI + UIKit 混编Jetpack Compose + ViewMaterial 3 + cupertino_icons
DIResolver / Factory / 手动Hilt (Dagger)get_it / riverpod Provider
网络URLSession / Alamofire / MoyaOkHttp / Retrofit / Ktordio + retrofit (retrofit/dart)
存储GRDB / Realm / SwiftDataRoom / Realm / DataStoredrift / sqflite / realm / isar
图片KingfisherCoilextended_image / cached_network_image
响应式Combine / Async-AlgorithmsFlow / CoroutinesStream / RxDart
路由swift-navigation / CoodinatorNavigation Compose / ARoutergo_router / auto_route
埋点自研 + Firebase自研 + Firebase自研 + firebase_analytics
崩溃Crashlytics / Sentry / BuglyCrashlytics / Sentry / BuglyCrashlytics / Sentry
CIXcode Cloud / fastlane + GitHub ActionsGitHub Actions + gradleCodemagic / GitHub Actions

2.3 工程分层

┌─────────────────────────────────────────┐
│  App Shell (启动、路由、DI 容器)         │
├─────────────────────────────────────────┤
│  Features (按业务域拆分,互不依赖)       │
│  - Home / Profile / Order / IM ...      │
├─────────────────────────────────────────┤
│  Core / Domain (协议、模型、用例)        │
├─────────────────────────────────────────┤
│  Data (Repository、网络、缓存、本地数据) │
├─────────────────────────────────────────┤
│  Infrastructure (网络/存储/日志/埋点/安全)│
├─────────────────────────────────────────┤
│  Platform SDK (Foundation/AndroidX/Dart) │
└─────────────────────────────────────────┘

依赖规则(严格单向):

  • App → Features → Core → Infrastructure → Platform
  • Features 之间禁止横向依赖;跨 Feature 走 Core 协议 + 路由。

2.4 包/目录命名(约定式)

features/
  home/
    presentation/   (View + ViewModel)
    domain/         (UseCase + Entity)
    data/           (Repository 实现 + DTO)
    di/             (依赖注入配置)
core/
  common/           (扩展、工具)
  designsystem/     (UI Kit)
  model/            (全局共享模型)
  network/          (网络基建)
  storage/          (存储基建)
infra/
  tracking/  push/  crash/  logger/  config/

2.5 多环境配置

iOSAndroidFlutter
配置文件.xcconfiggradle + buildConfigField--dart-define / flutter_dotenv
多 Target / Flavor多 Target + SchemeproductFlavors--flavor
Bundle/Application ID后缀 .dev / .staging后缀 .dev / .staging共用 + 切 Bundle
图标Asset Catalog 多套res/src/main/dev/res--flavor 切图标
域名切换xcconfig 注入 Info.plistBuildConfig启动读 env 文件

iOS xcconfig 示例:

// Dev.xcconfig
API_BASE_URL = https:\/\/api.dev.example.com
APP_DISPLAY_NAME = AppName-dev
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG

Android flavor 示例:

kotlin
flavorDimensions += "env"
productFlavors {
    create("dev")     { dimension = "env"; applicationIdSuffix = ".dev"     }
    create("staging") { dimension = "env"; applicationIdSuffix = ".staging" }
    create("prod")    { dimension = "env" }
}

Flutter --dart-define

bash
flutter run \
  --dart-define=API_BASE_URL=https://api.dev.example.com \
  --dart-define=ENV=dev \
  --flavor dev

2.6 CI/CD 流水线

PR 阶段:
  - Lint (SwiftLint / Detekt / dart format + analyze)
  - Unit Test
  - Build (Debug)

Merge 阶段:
  - Build (Release)
  - 上传符号 (dSYM / mapping.txt / .symbols)
  - 内测包 (TestFlight / Play Internal)

Release 阶段:
  - 灰度 (Phased Release / Staged Rollout)
  - 监控告警阈值
  - 一键回滚开关 (Feature Flag)

三、iOS 工程架构

3.1 模块化方案对比

方案优点缺点
CocoaPods生态成熟、二进制化容易安装慢、Pods.xcodeproj 易冲突
Swift Package Manager苹果原生、Xcode 集成、自动管理依赖不支持资源脚本、二进制 framework 集成弱
BBBundle / 自研二进制编译速度快维护成本高
Tuist / Bazel大型项目编译加速学习曲线陡

经验:中小型项目用 SPM 优先;二进制化需求强 → SPM + XCFramework;超大型 → Tuist。

3.2 路由方案

方案实现适用
URL Router(MGJRouter / CTMediator)字符串注册 + 解析解耦彻底、动态化、不利于编译检查
Target-Action(CTMediator)runtime 调用 target-action中间件轻;OC 友好、Swift 弱
Protocol-Router(BeeHive)协议 + 实现 bind强类型;模块加载复杂
类型安全 + Coordinator(swift-navigation / Combine)强类型、可测试纯 Swift 项目首选
DeepLink 桥接URL Router + 统一入口处理 Push / Universal Link / Scheme

混合方案:对外(推送、DeepLink、Web Bridge)用 URL Router;App 内跳转用强类型 Coordinator

3.3 资源管理

  • 资源命名:<module>_<feature>_<role>_<state>.png(例:home_avatar_default)。
  • Bundle 隔离:每个 Feature Module 自带 .bundle
  • Asset Catalog:On-demand resources + App Thinning。
  • 颜色用 Color Set(暗黑模式自动适配)。

3.4 启动优化分层

Pre-main:
  +load → initialize → 静态初始化器
  ▼ 优化:合并动态库、移除无用 +load、二进制重排 (Order File)

Main 后:
  willFinishLaunching → didFinishLaunching → 首帧
  ▼ 优化:
     - 启动任务分级(必须/可延迟/可后台)
     - 启动器(Task Scheduler)并行
     - Flutter Engine 预热(混合栈)
     - 首页用快照占位

四、Android 工程架构

4.1 模块化

  • Multiple Module Gradleapp / feature-xxx / core-xxx / library-xxx
  • buildSrc / Version Catalog (libs.versions.toml):依赖统一管理。
  • 构建加速:并行构建、配置缓存 (org.gradle.unsafe.configuration-cache=true)、模块二进制化 (AAR)。

4.2 路由

方案备注
ARouter阿里出品,业界主流
TheRouter字节出品,支持 KSP
Navigation Compose官方,类型安全(@Serializable route)
DeepLink Dispatch处理 App Link / Scheme

4.3 资源

  • 模块资源前缀:resourcePrefix "home_"
  • VectorDrawable 优先;位图 WebP。
  • 多 Language:values-zh / values-ja / values-ar

五、Flutter 工程架构

5.1 分层

lib/
  main.dart
  app/                 (App 入口、主题、路由)
  core/                (网络、存储、错误、日志)
  data/                (Repository、DTO、Mapper)
  domain/              (Entity、UseCase、Repository 接口)
  presentation/        (Page、Widget、Controller)
  shared/              (DesignSystem、Utils、Extensions)
  gen/                 (l10n、json_serializable 生成)

5.2 状态管理选型

方案适用心智
Riverpod 2.x中大型项目首选编译期安全、可测试
Bloc / Cubit复杂状态机(IM、订单)事件驱动、模板代码多
GetX快速原型 / 小项目灵活但易滥用全局状态
Provider简单场景Riverpod 前身,新项目不推
Signal / Flutter Hooks局部状态轻量

5.3 路由

  • go_router:官方推荐,声明式 + DeepLink 友好。
  • auto_route:类型安全 + 代码生成,中大型项目首选。
  • 统一 RouteGuard:登录拦截、权限校验、埋点。

5.4 依赖注入

  • get_it:Service Locator 模式,简洁。
  • riverpod Provider:纯声明式 DI。
  • injectable:编译期生成 get_it 注册代码。

六、通用模块封装

6.1 网络模块

6.1.1 分层

API DSL(业务调用)

RequestBuilder(路径/方法/参数/头)

Client(执行器)

Interceptor Chain(鉴权/签名/加密/日志/重试/缓存)

Transport(URLSession / OkHttp / HttpClient)

Decoder(JSON → DTO → Domain Model)

ErrorMapper(HTTP/IO → App Error)

6.1.2 接口设计(伪代码)

swift
// 业务侧
let resp: UserDTO = try await API.request(.user(id: "123"))
kotlin
suspend fun getUser(id: String): UserDTO =
    api.get("users/$id")
dart
final user = await api.get<UserDTO>('users/123', parse: UserDTO.fromJson);

6.1.3 关键能力清单

能力实现
BaseURL 多环境xcconfig / BuildConfig / --dart-define
HTTPDNSHappyDNS / OkHttp Dns SPI / cronet_http
TLS PinningURLSessionDelegate / CertificatePinner / SecurityContext
HTTP/2 / HTTP/3URLSession 默认 / OkHttp 默认 / cronet_http
拦截器链Adapter/Interceptor 模式,按序注册
鉴权拦截自动注入 Token,401 触发刷新
签名拦截HMAC-SHA256 签名参数 + 时间戳 + Nonce
加密拦截IJK / AES-GCM 整包加密;敏感字段单独加密
日志拦截Release 脱敏;cURL 命令复现
缓存拦截HTTP Cache-Control + 本地策略
重试拦截指数退避 + 抖动;幂等性校验
超时分层connect 5s / read 10s / total 30s
并发控制同域 6 连接上限;串行队列防风暴
优先级调度UI 请求 > 后台同步;URLSessionTask.priority
取消机制CancellationToken / CoroutineScope / CancelToken
断点续传Range Header + 本地 offset 持久化
上传multipart/form-data、流式、分片
下载文件流写盘、原子重命名、断点续传
SSLPinning 轮换多 SPKI Hash 备用,避免换证书全挂

6.1.4 错误模型

AppError
 ├─ NetworkError      (无网络/超时/DNS)
 ├─ ServerError       (5xx)
 ├─ BusinessError     (业务码 + 提示文案)
 ├─ AuthError         (401/403,触发登录)
 └─ ParseError        (JSON 解析失败)

关键:HTTP 200 也可能携带业务错误({code: 1001, msg: "余额不足"});统一拦截器识别 code,转 BusinessError

6.1.5 弱网策略

  • 接口幂等设计(POST 也要带 idempotency-key)。
  • 关键操作三连:请求 + 本地草稿 + 重试队列。
  • 离线队列:失败任务落 SQLite,恢复网络后回放。

6.1.6 安全

  • 全站 HTTPS + TLS 1.3 + Pinning。
  • 敏感参数加密(RSA 换 AES Key → AES-GCM 加密 body)。
  • 请求头加 X-Sign + X-Timestamp + X-Nonce,服务端校验防重放(5min 窗口)。

6.2 登录鉴权模块

6.2.1 鉴权模型

模式说明
Session + Cookie老式 Web 模式;移动端少用
Bearer Token(JWT)无状态、易水平扩展;Token 易被盗
OAuth 2.0三方授权码模式 / PKCE
Refresh Token 轮换AT 短(15min) + RT 长(30d),RT 用一次换一对
设备指纹绑定RT 与设备 ID 绑定,被盗换设备失效
SSO / CAS多 App 共享登录(集团内)

6.2.2 模块能力清单

AuthModule
 ├─ 登录入口
 │   ├─ 账号密码
 │   ├─ 手机验证码(一键登录/本机号认证)
 │   ├─ 第三方(微信/QQ/微博/Apple/Google/Facebook)
 │   ├─ 邮箱
 │   └─ 生物识别(Face ID / 指纹)— 复登
 ├─ Token 管理
 │   ├─ 存储(Keychain / EncryptedSharedPreferences / flutter_secure_storage)
 │   ├─ 自动刷新(401 → 刷新 → 重放原请求)
 │   ├─ 并发刷新去重(单飞 SingleFlight)
 │   └─ 多端互踢(401 + 特定 code → 强制下线)
 ├─ 登录态分发
 │   ├─ 全局状态(StateFlow / Stream / Combine)
 │   ├─ 登录态变化通知
 │   └─ 未登录拦截(路由 Guard)
 ├─ 退出登录
 │   ├─ 服务端注销 RT
 │   ├─ 清理本地(Token / 缓存 / 业务 DB)
 │   ├─ 重置路由到登录页
 │   └─ 重启网络拦截器
 └─ 风控
     ├─ 异地登录提示
     ├─ 频次限制
     └─ 验证码挑战

6.2.3 Token 刷新关键细节

  • SingleFlight:多个并发 401 请求只触发一次刷新,其它挂起等待。
  • 刷新失败:清空 Token → 路由到登录页;不再无限重试。
  • 刷新 RT 时:必须锁定 RT,防止多请求并发用同一个旧 RT(会被服务端撤销)。
  • Apple Sign In:必须用 ASAuthorizationAppleIDRequest,且服务端校验 identityToken JWT。

6.2.4 Apple 强制项

  • Sign in with Apple:只要支持了三方登录(Google/Facebook/微信),就必须提供 Apple Sign In(仅 iOS 13+ 实机生效)。
  • 账号注销:必须提供,Hard Delete。

6.3 图片框架

6.3.1 加载流水线

URL → 内存缓存(LRU) ─命中─→ 显示
                       └─未命中→ 磁盘缓存 ─命中─→ 解码 → 内存缓存 → 显示
                                              └─未命中→ 网络 → 解码 → 磁盘 + 内存 → 显示

6.3.2 关键能力

能力关键
降采样不解码原图,按目标尺寸 downsample;内存节省 90%+
异步解码子线程解码位图,主线程只渲染
格式WebP / HEIC / AVIF / GIF / APNG
圆角/边框cornerRadius + masksToBounds 触发离屏渲染,应改用带 mask 的位图
过渡动画渐入 / 淡入
占位/错误图placeholder / error widget
进度网络进度回调
缓存控制Cache-ControlETagLast-Modified
缓存淘汰LRU 内存 + Disk LRU(按大小、按天数)
列表复用cell/Item 复用时取消旧请求,避免错位
优先级可视区域 > 预加载 > 后台
CDN 裁剪客户端按 ImageView 尺寸拼 ?w=200&h=200

6.3.3 选型

平台首选备注
iOSKingfisherSWift 原生、模块化、扩展强
iOS 老项目SDWebImageOC 老牌、稳定
AndroidCoilKotlin-first、协程、生命周期感知
Android 老项目Glide老牌稳定
Flutterextended_image功能最全(缓存、手势、裁剪、编辑)
Flutter 简单cached_network_image用法简单

6.3.4 长列表优化要点

  • 设置 prefetchWindowitemExtent 提升滚动性能。
  • 取消不可见项的请求。
  • 缩略图占位,原图加载后渐变替换。
  • 不在滚动时触发 setState(用 NotificationListener 判断 idle 才刷新)。

6.4 存储模块

6.4.1 分层选型

数据类型iOSAndroidFlutter
小键值UserDefaults / KeychainDataStore (Prefs) / EncryptedSharedPreferencesshared_preferences / flutter_secure_storage
敏感小数据KeychainEncryptedSharedPreferences + Keystoreflutter_secure_storage
结构化GRDB / SQLite.swift / SwiftDataRoom / SQLDelightdrift / sqflite / isar
对象SwiftData / Core DataRoomrealm / isar
大文件FileManager + mmapFile + MMKVpath_provider + file
KV 高性能MMKV / YapDatabaseMMKVmmkv (Flutter plugin)
全文搜索SQLite FTS5SQLite FTS4/5drift + FTS5

6.4.2 封装要点

  • 统一抽象Storage 协议(get/set/delete/observe),底下多实现。
  • 加密:敏感字段用 Keychain/Keystore,整体 DB 用 SQLCipher。
  • 迁移:版本号 + Migration 脚本;首次安装走 seed
  • 观察@FetchRequest(SwiftData)/ Flow<List<Entity>>(Room)/ Stream(drift)。
  • 线程:DB 操作必须在专用队列 / IO Dispatcher / Isolate。

6.5 日志模块

6.5.1 设计

Logger
 ├─ Level (Debug / Info / Warn / Error / Fatal)
 ├─ Domain (Net / DB / Auth / Business)
 ├─ Format (结构化: JSON / 文本)
 ├─ Sink
 │   ├─ Console (开发)
 │   ├─ File (按日切分、压缩、上传)
 │   ├─ Remote (错误聚合,走 Crashlytics / Sentry)
 │   └─ OSLog (Instruments 联动)
 └─ Filter (按 Domain / Level / Tag)

6.5.2 关键点

  • Release 关闭 Debug,开启 Info+ File 滚动(容量上限 5MB×3 文件)。
  • 格式[time][level][domain][file:line] message {context}
  • 结构化:日志带 event_id / trace_id,方便后端关联。
  • 脱敏:手机号、邮箱、Token 中间打码;触发器配置规则。
  • 性能:写文件用 mmap 或 async queue;不要阻塞主线程。
  • OSLog / Logcat:开发期直接看;上线用文件归档。

iOS 用 os.Logger(统一系统日志,Instruments 联动):

swift
let log = Logger(subsystem: "com.example.app", category: "network")
log.error("HTTP \(statusCode) for \(url)")

6.6 路由模块

6.6.1 能力清单

  • 注册:Feature 模块自注册路由表(避免中心化耦合)。
  • 解析:支持路径参数 /user/:id、查询参数。
  • 拦截器:登录守卫、权限校验、埋点、动画。
  • 结果回传presentForResult
  • DeepLink:统一收口 Universal Link / Scheme / Push / Web Bridge。
  • 嵌套导航:Tab + 内部 Stack。
  • Web fallback:App 内没装该模块时打开 H5。

6.6.2 抽象

swift
protocol Router {
    func register(_ pattern: String, builder: @escaping (Params) -> AnyView)
    func route(to url: URL, context: Any?) -> Bool
    func canHandle(_ url: URL) -> Bool
}

6.6.3 路由表声明式注册

kotlin
@Route(path = "/user/:id")
class UserActivity : Activity()

@Serializable
data class UserRoute(val id: String) : Route

6.7 埋点模块

6.7.1 模型

Event
 ├─ name           (e.g. "login_submit")
 ├─ properties     (Map<String, Any>)
 ├─ user_id        (登录后)
 ├─ device_id      (设备稳定 ID)
 ├─ session_id     (启动/前台切换生成)
 ├─ timestamp      (UTC)
 └─ trace_id       (跨端串联)

6.7.2 能力

  • 手动埋点 + 全埋点(无码)+ 可视化埋点三种混合。
  • 离线缓存:本地 SQLite/Realm,弱网批量上报。
  • 批量上报:合并 N 条 / 定时 T 秒 / 大小 B 字节 触发。
  • 重试:失败回滚到队列。
  • 丢弃策略:超过容量优先丢弃低优先级。
  • 合规:用户同意跟踪前不上报广告 ID;IDFA/AAID 可空。
  • 统一入口:所有上报走 Tracker.track(...),禁止散落调用第三方 SDK。
  • 多平台分发:一个事件同时分发到 Firebase + 自研 + AppsFlyer。

6.8 推送模块

6.8.1 抽象层

PushManager
 ├─ register()              (申请 Token)
 ├─ onToken(cb)
 ├─ onMessage(cb)           (前台收到)
 ├─ onNotificationTap(cb)   (通知点击)
 ├─ onBackground(cb)        (静默推送 / Data Only)
 └─ channel dispatcher
     ├─ APNs
     ├─ FCM
     ├─ HuaweiPush / XiaomiPush / OPPOPush / VIVOPush
     └─ Custom (WebSocket)

6.8.2 细节

  • 统一 Token 上报:每端 Token 不同,后端按 device_type + token 维度存储。
  • 通知点击跳转:走统一路由,push_payload = { route, params }
  • 静默推送:iOS content-available:1;Android data only;用于数据同步。
  • 富媒体:iOS Notification Service Extension 解码图;Android BigPictureStyle
  • iOS Live Activities / Android Foreground Service:实时场景。
  • 权限时机:不要冷启动就申请;先用 In-App Pre-Prompt 解释价值。
  • 推送到达率监控:客户端上报收到率,后端聚合分析。

6.9 崩溃与异常

6.9.1 捕获

平台机制
iOSNSSetUncaughtExceptionHandler + signal(SIGABRT/SEGV/...) + Mach 异常
Android (Java)Thread.setDefaultUncaughtExceptionHandler
Android (Native)sigaction + breakpad
FlutterrunZonedGuarded + FlutterError.onError + PlatformDispatcher.instance.onError
Dart IsolateIsolate.current.addErrorListener

6.9.2 处理流程

1. 异常捕获
2. 收集堆栈、设备、App 版本、User、Session
3. 本地缓存(关键,防止上报失败丢失)
4. 重启主进程 / 友好弹窗
5. 后台批量上报
6. 服务端符号化 + 聚合 + 告警

6.9.3 符号化

  • iOS:dSYM 与 Build 一一对应;上传 Crashlytics / Sentry。
  • Android:mapping.txt(R8)+ Native .so.debug(Breakpad .sym)。
  • Flutter:flutter symbolize + app.ios.symbols

6.9.4 监控指标

  • 崩溃率:sessions-based(< 0.1% 行业基线)。
  • ANR 率(Android 5s 主线程阻塞、iOS 启动卡死 watchdog)。
  • OOM 率(iOS Jetsam;Android Low Memory Killer)。
  • 自定义用户级影响率。

6.10 UI 组件库与主题

6.10.1 设计令牌(Design Token)

Color
 ├─ brand.primary / secondary
 ├─ semantic.success / warning / error / info
 ├─ text.primary / secondary / disabled
 └─ bg.primary / secondary / elevated

Typography
 ├─ display / headline / title / body / caption / overline
 └─ 每级 size / weight / line-height

Spacing
 └─ 4 / 8 / 12 / 16 / 24 / 32 (8pt grid)

Radius / Elevation / Motion

6.10.2 抽象

kotlin
interface ThemeProvider {
    val colors: ColorScheme
    val typography: Typography
    val shapes: Shapes
}

6.10.3 关键

  • 暗黑模式:所有颜色定义两套;不用硬编码 Color.black
  • Dynamic Type / Font Scaling:iOS 用系统字号;Android sp 单位;Flutter MediaQuery.textScaleFactor
  • RTL:用 leading/trailing 而非 left/right
  • 组件库分层:原子(Button)→ 分子(FormField)→ 有机体(LoginForm)→ 模板(Page)。
  • 预览与文档:Storybook / SwiftUI Previews / Widget Catalog。

6.11 权限模块

6.11.1 统一封装

Permission
 ├─ status  (notDetermined / denied / restricted / granted)
 ├─ request() -> Status
 └─ openSettings()

每类权限独立 Provider;业务调用:

swift
let granted = await Permission.camera.request()
if !granted { showRationaleAndOpenSettings() }

6.11.2 关键

  • Pre-Prompt:在系统弹窗前,自绘弹窗解释为什么需要。
  • Denied 后:跳系统设置;不要无限弹。
  • 状态恢复:权限变更后,UI 同步刷新(监听 UIApplication.willEnterForeground)。
  • iOS 14+ Local Network / Tracking / Photo Library Limited:注意新增的细化权限。
  • Android 13+ Notification / Photo Picker:必须运行时申请。

6.12 设备与运行时上下文

ContextProvider
 ├─ Network (wifi/cellular/none/unknown + quality)
 ├─ Battery (level/lowPower/charging)
 ├─ AppLifecycle (active/inactive/background)
 ├─ MemoryPressure (warning)
 ├─ DeviceInfo (model/os/version/locale/timezone)
 ├─ Display (size/scale/orientation/darkMode)
 └─ PermissionStatus (各权限最新状态)

业务通过 DI 注入抽象接口订阅;禁止散落调用 UIDevice.currentConnectivityManagerMediaQuery


6.13 性能监控

指标工具
启动Xcode MetricKit / Firebase Performance / 自研打点
卡顿CADisplayLink 丢帧 / Runloop 状态耗时 / Choreographer / FrameCallback
内存task_vm_info.phys_footprint / Debug.MemoryInfo / MemoryUsage
能耗MetricKit MXCPUUsage / Energy Log / Android Battery Historian
网络请求耗时 / 成功率 / 重试率
FPSDisplayLink / vsync
磁盘沙盒大小、缓存大小
线上 Crash / ANR / OOMCrashlytics / Sentry / 自研
  • 线下:Instruments(Time Profiler / Leaks / System Trace)、Android Studio Profiler、Flutter DevTools。
  • 线上:APM SDK(自研或第三方),按采样上报,关键路径全量。

6.14 配置中心与 Feature Flag

6.14.1 抽象

ConfigService
 ├─ getString(key, default)
 ├─ getBool(key, default)
 ├─ getInt / getDouble / getJSON
 ├─ stream(key)   (实时监听变化)
 └─ sources: local (plist/json) < remote (Firebase Remote Config / 自研)

6.14.2 用途

  • 远程开关:紧急下线功能、灰度发布。
  • A/B 测试:按用户分组。
  • 动态文案 / URL / 业务参数:不发包即可调。
  • 降级:服务异常时切兜底配置。

6.14.3 关键

  • 本地兜底:远程拉取失败时用打包内置 default。
  • 缓存策略:本地存最近一次值,启动先用本地,后台异步刷新。
  • 变更广播:通过 Stream / Combine / Flow 通知订阅者。
  • 审计:每次取值记录来源(local/remote/exp)。

6.15 安全模块

维度实现
传输TLS 1.3 + Pinning + HTTPDNS
存储Keychain / Keystore / SQLCipher / MMKV 加密模式
代码iOS 宏混淆 / Android ProGuard R8 / Flutter 字符串加密
反调试ptrace PT_DENY_ATTACH / sysctl P_TRACED
越狱/Root文件特征检测 / Magisk 检测
Hook 检测Frida 端口/线程 / Substrate / Xposed
完整性签名校验 + 服务端校验
设备指纹IDFV/IDFA/Android ID/OAID + 服务端聚合
防重放时间戳 + Nonce + 签名
App Attest / Play Integrity硬件级证书,防作弊
安全键盘自绘数字键盘,金融场景必用

七、跨端混合架构

7.1 Flutter 混合方案

方案说明
Add-to-App官方,原生工程嵌入 Flutter Module;按需创建 Engine
Flutter Boost字节,混合栈管理;复用单 Engine,节省内存
flutter_thrio类 Boost,更轻量
Multi-EngineFlutter 3.0+ Engine Group,多页面独立 Engine,互不影响

7.2 通信层封装

  • 统一 FlutterBridge:所有 Channel 注册到中央管理器,业务侧调用强类型接口(Pigeon 生成)。
  • 生命周期联动:原生页面销毁 → 通知 Flutter 释放对应资源(ImageCache、Stream)。
  • 内存联动:iOS Memory Warning → Flutter didHaveMemoryPressure → 释放图片缓存。
  • 线程模型:Flutter UI 线程独立;耗时操作走 Isolate;Channel 默认在主线程,注意切换。

7.3 动态化(受限场景)

方案适用
自研 DSL(JSON 驱动 UI)营销活动页
Kraken / Hippy / Sonic三方成熟方案
WebView + JS Bridge高频改动的活动 / 富文本
小程序引擎(Taro / uni-app)国内多端分发

注意:iOS 严禁动态下发可执行代码(除 Apple 例外清单);动态化应走"解释执行"而非"代码下发"。


八、可演进性与技术债

8.1 演进策略

  • 架构小步快跑:每迭代一次重构一个模块(Strangler Fig 模式)。
  • 抽象稳定后再下沉:先业务跑通,再抽 Core;过早抽象等于负债。
  • 接口先行:跨团队约定接口契约,并行开发。
  • 兼容窗口:旧 API 标记 deprecated → 灰度 → 下线,给业务至少一个版本窗口。

8.2 技术债管理

信号应对
编译时间 > 10 分钟拆模块、二进制化
PR 改动 50+ 文件模块边界模糊,重新划分
同样 Bug 反复出现加测试、加 lint 规则
启动崩溃率上涨APM 告警 + 紧急回滚
业务抱怨"加功能越来越难"重构该模块,引入抽象

8.3 文档与契约

  • 架构决策记录(ADR):每个重大决策写下背景、选项、结论、后果。
  • API 契约:OpenAPI / GraphQL Schema / Protobuf,前后端共用。
  • 模块 README:模块职责、依赖、对外 API、变更负责人(CODEOWNERS)。

8.4 监控驱动架构

  • 上线前先埋 APM / 业务监控 → 再做架构演进。
  • 每次重构对比前后指标(崩溃率、性能、包大小)→ 数据驱动决策。
  • 设置 SLO(如 P99 启动 < 1.5s、崩溃率 < 0.1%),违反即治理。

基于 VitePress 构建 · 部署于 Cloudflare Pages