Skip to content

异步后台任务、保活、系统能力 ​

一句话定位 ​

这一模块不再把 WorkManager、Foreground Service、Flutter、iOS 背景能力平铺罗列,而是按知识导航树串成一条业务落地主线:

Android 主线 → Flutter 边界 → iOS 约束 → 业务落位

读完后,应该能先判断任务是否属于 Android 可靠后台能力,再看 Flutter 只是调用边界还是执行主体,最后用 iOS 约束收口成能真正上线的产品方案。

模块目标 ​

建立 Android / Flutter / iOS 在后台任务、持续任务、系统调度、保活边界上的现实认知,重点不是“列能力”,而是回答:

  • 这个任务到底该挂在哪一层?
    • 一句话答:先按“Android 可靠能力 → Flutter 调用 / 表达层 → iOS 约束”判断任务归属,再谈落位。
  • 哪些能力是 Android 主线可以可靠承接的?
    • 一句话答:WorkManager(延迟可恢复)、Foreground Service(持续用户感知)、AlarmManager(定时边界,受限制)等系统级能力。
  • Flutter 自己能描述什么,不能替代什么?
    • 一句话答:Flutter 能表达业务意图、调用原生能力,但不能替代宿主对后台执行窗口的授权。
  • iOS 会在哪一步直接砍掉你的乐观假设?
    • 一句话答:在“无通用强保活、后台窗口由系统决定”这一步,依赖准点或持续执行的设计会被砍掉。
  • 录音、下载、上传、推送、同步这些任务最终应该如何落位?
    • 一句话答:按能力树归位:Android 用系统能力承接执行,Flutter 做调用层,iOS 收缩为机会窗 + 服务端兜底。

模块成熟度与当前缺口 ​

当前模块可视为:L2.5 → L3 过渡中。

  • 已有:Android / Flutter / iOS 三层判断框架 + 录音转写业务总案例
  • 已有:WorkManager / FGS / Push / Download 等主线专题
  • 已补:recording-sync-state-machine、recording-upload-handoff、push-miss-sync-recovery 三个最小闭环样板

换句话说,本模块最重要的后续工作不是再开一批后台 API 词条,而是把已经写出来的判断框架真正落到可运行样板。

先记住一张判定图:后台任务不是一个问题 ​

例子 1:会议录音转写为什么不能被当成“一个后台任务”? ​

  • 错误想法:录音、上传、转写、回流都算“后台录音功能”,丢给一个前台服务 / 一个 Flutter plugin 统一解决。
  • 正确拆法:
    1. 录制阶段:持续、用户可感知 → Android 前台服务 / iOS 合法音频模式
    2. 上传阶段:可恢复、可能断网 → WorkManager / 系统允许的后台上传模型
    3. 转写阶段:长耗时、可重试 → 服务端任务状态机
    4. 回流阶段:尽快看到结果但不承诺秒达 → 推送 + 前台补拉 + 机会窗同步

如果把四段混成一个任务,Android 还能“勉强跑”,iOS 会直接暴露设计错误。

例子 2:为什么“silent push 到了就同步”经常上线后失真? ​

  • 表面现象:测试机能收到静默推送,线上部分用户却迟迟不同步
  • 根因:silent push 只是“系统可能给你一个机会窗”,不是后台长期执行许可证
  • 正确处理:推送只做“加速看见结果”,真正一致性建立在服务端状态机 + 前台补拉 + 下次启动补同步上

本模块要回答的问题 ​

  • WorkManager 是什么,不是什么?
    • 一句话答:是延迟、可恢复、带约束感知的后台任务调度器;不是精准定时器,也不保证立即执行。
  • Foreground Service 和 WorkManager 的边界在哪里?
    • 一句话答:前台服务要求常驻通知、用户可见,适合持续长任务;WorkManager 适合延迟可恢复任务,由系统在合适时机调度。
  • iOS 后台音频、后台刷新、silent push 的真实边界是什么?
    • 一句话答:都是受限能力:音频需声明且播放中,后台刷新 / 静默推送的时机由系统决定,不能当可靠保活。
  • Flutter 自己能做什么,必须借原生做什么?
    • 一句话答:Flutter 能组织 UI 与业务逻辑,后台执行 / 保活必须借原生宿主能力(plugin / channel 下放)。
  • 录音、下载、推送、同步这些任务应该怎么落位?
    • 一句话答:按平台能力树落位:系统级能力承接执行,Flutter 表达意图,iOS 按保守边界收口。

知识导航树:从 Android 能力到业务落位 ​

第一层:Android 主线(先建立可靠后台能力心智) ​

先读:WorkManager / ForegroundService / AlarmManager 对比

这一层解决:

  • WorkManager / Foreground Service / AlarmManager 分别适合什么任务
  • 哪些任务属于延迟可恢复、哪些属于持续用户感知、哪些涉及定时边界
  • Android 电池优化、厂商限制、后台冻结为什么会改变任务存活率
  • “协程 / 线程 / 异步”为什么不等于“可靠后台能力”

Android 主线深入专题:

适合带着这些问题进入:

  • 任务退后台后为什么经常不稳定?
    • 一句话答:后台冻结、电池优化、厂商限制会暂停或限制执行;稳定性取决于系统对后台任务的容忍度,不是代码写得对就稳定。
  • 为什么短任务不该滥用 Foreground Service?
    • 一句话答:前台服务要求常驻通知、用户可见、资源开销大;短任务滥用等于过度承诺,反而更容易被系统收紧。
  • 为什么精确定时要先谈系统政策,而不是先写调度代码?
    • 一句话答:系统政策(Doze、厂商白名单、省电策略)决定能否准点执行,代码写得再好也改变不了系统调度约束。

第二层:Flutter 边界(再判断 Flutter 只是调用层还是执行层) ​

再读:Flutter 后台能力边界

这一层解决:

  • Flutter 自己在后台能力上能做什么、不能做什么
  • compute / isolate 为什么只能解决 CPU 与隔离,不解决系统授权
  • Flutter plugin / channel 如何把任务下放到原生后台能力
  • 为什么跨端层适合表达业务意图,但不应假装自己拥有宿主级后台能力

适合带着这些问题进入:

  • 这件事是 Flutter 可以独立完成,还是必须桥接原生?
    • 一句话答:凡涉及宿主后台执行授权 / 保活的都必须桥接原生;Flutter 只做调用层与业务表达。
  • isolate 能不能替代 WorkManager / Foreground Service?
    • 一句话答:不能:isolate 只解决 CPU 计算与隔离,不解决系统是否授予后台执行窗口。
  • Flutter 页面退下去后,为什么 Dart 代码不等于还拿着后台执行窗口?
    • 一句话答:页面退出后 App 可能被挂起或回收,Dart 代码能否继续跑取决于宿主进程是否存活、系统是否给执行窗口。

第三层:iOS 约束(最后用最严格平台收口设计) ​

最后读:iOS 后台能力现实边界

这一层解决:

  • iOS 不存在通用强保活的现实边界
  • 后台音频、定位、下载、silent push、Background Fetch 到底各能承载什么
  • 为什么 BGTask / 后台刷新不是准点调度器
  • 跨端方案为什么必须以 iOS 最保守约束反推产品能力

适合带着这些问题进入:

  • Android 能成立的后台模型,为什么在 iOS 上不成立?
    • 一句话答:iOS 没有通用强保活,后台执行靠白名单例外与机会窗,Android 的“后台模型”心智在 iOS 直接失效。
  • 哪些能力是白名单例外,哪些只是机会窗?
    • 一句话答:后台音频、定位、VoIP 等是声明式例外;后台刷新、silent push 只是系统给的“机会窗”,不保证触发。
  • 产品承诺“持续同步 / 准点执行”时,跨端设计应该如何降级?
    • 一句话答:降级为“尽力而为 + 下次启动补同步”或服务端拉取兜底,不承诺准点或持续执行。

第四层:业务落位(把能力树变成真实方案) ​

最后收口到业务方案,而不是停在 API 名词。

先读业务案例专题页:

这一层的判断框架依然成立:

  • 录音类:先问是否需要持续用户可感知,再判断前后台差异
  • 下载 / 上传类:先问是否要求可靠完成、断点续传、系统托管
  • 同步类:先问是机会型刷新,还是必须准点 / 必达
  • 推送唤醒类:先问平台是否真的授予唤醒窗口,而不是把消息通道当作常驻保活

推荐阅读路径:按决策链而不是按知识点平铺 ​

路径 A:先做 Android 方案,再判断跨端能否成立 ​

  1. WorkManager / ForegroundService / AlarmManager 对比
  2. Flutter 后台能力边界
  3. iOS 后台能力现实边界
  4. 回到本页“业务落位树”,确认产品方案是否要降级

路径 B:先查“Flutter 能不能自己做后台任务” ​

  1. Flutter 后台能力边界
  2. WorkManager / ForegroundService / AlarmManager 对比
  3. iOS 后台能力现实边界

路径 C:先查“跨端业务为什么上线后不稳定” ​

  1. iOS 后台能力现实边界
  2. WorkManager / ForegroundService / AlarmManager 对比
  3. Flutter 后台能力边界
  4. 再回到业务落位,决定是否改产品承诺或服务端配合

导航总表:每一层读什么 ​

导航层先回答什么对应文档关键判断
Android 主线任务该交给哪种 Android 后台能力WorkManager / ForegroundService / AlarmManager 对比WorkManager / Foreground Service / AlarmManager 的职责边界
Flutter 边界Flutter 是执行主体,还是原生后台能力的调用层Flutter 后台能力边界isolate 不等于后台授权,plugin / channel 才能对接宿主能力
iOS 约束跨端方案落到 iOS 时哪些假设会失效iOS 后台能力现实边界iOS 没有通用强保活,BGTask / silent push 都有严格现实边界
业务落位录音 / 下载 / 上传 / 同步 / 推送到底怎么设计录音转写:录制进行中 + 断点上传 + 会话同步 + 推送回流先拆业务阶段,再看系统授权、服务端状态机与结果回流

业务落位树:常见任务怎么顺着约束落地 ​

1. 录音 ​

  • 先看 Android 主线:是否需要持续、用户可感知、前台通知常驻
  • 再看 Flutter 边界:Flutter 页面可做控制层,但实际录音存续通常依赖原生能力
  • 最后看 iOS 约束:是否符合后台音频类白名单,以及产品是否接受系统更强限制

2. 下载 / 上传 ​

  • 先看 Android 主线:是否要可靠完成、断点续传、系统托管
  • 再看 Flutter 边界:Dart 逻辑更适合表达状态与交互,真正后台可靠性往往要借原生
  • 最后看 iOS 约束:是否必须改成系统允许的下载 / 上传模型,接受执行时机不完全可控

3. 同步 / 刷新 ​

  • 先看 Android 主线:是立刻执行、延迟执行,还是周期性机会执行
  • 再看 Flutter 边界:不要把 isolate 当成跨平台后台调度器
  • 最后看 iOS 约束:默认当机会型刷新处理,不承诺准点与持续存活

4. 推送唤醒 ​

  • 先看 Android 主线:推送更多是触发机会,不是无限后台时长许可证
  • 再看 Flutter 边界:消息到达后 Flutter 能处理的范围取决于宿主交给它的执行窗口
  • 最后看 iOS 约束:silent push 是否真正到达、是否被系统给予执行机会,都不可乐观假设

相近概念不要混 ​

概念它回答的问题不回答什么
协程 / Future / isolate任务如何并发执行OS 是否授予后台执行窗口
WorkManager延迟、可恢复、系统调度型后台任务如何运行持续用户可感知任务怎么常驻
Foreground Service用户可感知的持续任务如何在 Android 前台服务中存活iOS 是否存在等价通用能力
BGTask / Background FetchiOS 在特定机会窗里何时可能让你执行是否能准点、长期、稳定保活
plugin / channelFlutter 如何调用宿主能力Flutter 自己是否拥有宿主后台授权

与上一模块的衔接 ​

当你还在问“页面离开后为什么又重建 / 为什么对象没释放”时,先回到 ../02-memory-lifecycle/README.md。

当问题已经升级为“页面离开后任务还能不能继续、系统是否允许可靠后台执行”时,再进入本模块。

对应 labs 入口 ​

当前 docs/03-background-tasks/ 已落地两个可运行实验,其余仍在计划补齐:

当前最值得优先补的 3 个样板 ​

  1. recording-sync-state-machine
    • 已落地:Flutter host 演示 recording / waitingUpload / uploading / transcribing / synced / failed 状态收敛
  2. recording-upload-handoff
    • 已落地:Android host 演示 uploadSessionId 建立、失败保留本地文件、成功后再清理
  3. push-miss-sync-recovery
    • 已落地:shared 脚本演示“推送丢失 → 前台补拉 → 多端进入仍能同步”

复习检查题 ​

  1. 为什么这一模块要改成“Android 主线 → Flutter 边界 → iOS 约束 → 业务落位”的导航树?

    答:因为后台任务能否成立,首先取决于 Android 等宿主平台提供什么可靠能力;Flutter 更多是调用层和业务表达层;而最终跨端能否上线,往往要以 iOS 最严格约束收口。只有这样排,阅读顺序才与真实技术决策顺序一致。

  2. 为什么 Flutter isolate 不能直接当成后台任务方案?

    答:因为 isolate 解决的是并发执行与计算隔离,不解决系统是否授予后台执行窗口。没有宿主平台的后台授权,isolate 也无法凭空获得可靠后台时长。

  3. 为什么业务落位要放在最后,而不是一开始就按“录音 / 下载 / 同步”分文章?

    答:因为业务场景只是表象,不先分清 Android 主线能力、Flutter 边界与 iOS 约束,就会把很多表面相似的任务错误地归为同一种后台方案。先建能力树,再谈业务落位,才能避免方案先天不可落地。

  4. 为什么跨端后台设计默认要被 iOS 收紧?

    答:因为 iOS 没有 Android 式通用强保活能力,很多后台场景只能依赖白名单例外或机会窗。如果产品承诺建立在 Android 心智上,跨端上线后就会在 iOS 上出现执行时机漂移、任务不触发或能力被系统拒绝的问题。

备注 ​

本模块应优先结合真实业务样本,例如录音、下载、推送、后台同步与电池优化问题;但首页导航先解决“知识怎么走”,专题页再展开机制、参数、误配与排障。

站点构建时间:2026/8/24 23:43:17