在Repo接口定义中,常见两类函数:
- suspend functions:返回单一结果
- 普通函数返回 Flow:返回一个结果流
这两类函数在 Room DAO 等库中都有体现。例如 observeUsers() 返回 Flow,因为它是一个观察者,每次表变化都会发射新的用户列表。
一、通用原则
- 使用
suspend:当函数只产生一个结果时,例如数据库查询或调用外部服务 - 使用
Flow:当函数可能产生未知数量的结果时,例如 WebSocket 连接或数据库观察
不推荐在只期望一个结果的场景使用
Flow,原因包括:
- 语义误导 :
Flow暗示多个结果- 复杂度更高 :
suspend更简单、可读性更好、易于调试
二、朋友圈发送场景 ------ 使用 suspend
在发送朋友圈的业务中,很多操作都是一次性触发并返回结果,因此适合用 suspend:
- 发布朋友圈:用户点击"发送"后,等待结果返回
- 删除朋友圈:一次性操作,执行后即结束
- 点赞/取消点赞:触发后立即返回结果
- 发表评论:提交后返回成功或失败
示例接口
三、朋友圈动态场景 ------ 使用 Flow
朋友圈的另一类需求是实时动态更新,例如:
- 朋友圈列表:新内容发布后,列表需要自动刷新
- 特定朋友圈详情:点赞数、评论数随时变化
- 新朋友圈通知:好友发布新动态时推送
- 互动更新:点赞、评论的实时变化
示例接口

四、 ViewModel与状态管理
ViewModel 的可观察状态通常用 StateFlow 表示。 因此,API 暴露 Flow 会更容易消费,可以直接用 stateIn 转换为 StateFlow。
- 小型应用:用 Flow 到处都行,差别不大
- 复杂领域模型:滥用 Flow 会成为负担,
suspend更简洁 - 最佳实践:可以定义辅助函数,把
suspend转换为StateFlow,避免强行用 Flow everywhere (不要为了迎合 ViewModel 的需要而让数据层所有 API 都返回 Flow,而是保持数据层 API 的简洁性(使用挂起函数),然后在 ViewModel 层通过辅助函数将一次性操作的结果转换为 StateFlow)。
五、决策流程图

我总结了一个图,如下:
六、总结原则
| 特征 | suspend |
Flow |
|---|---|---|
| 数据特性 | 静态,一次性 | 动态,持续变化 |
| 结果数量 | 单次结果 | 多个值序列 |
| 使用场景 | 发送朋友圈、删除、点赞、评论 | 列表更新、通知、互动变化 |
| 生命周期 | 执行完即结束 | 持续到取消收集 |
简单记忆:
- 操作像 动词 (做某事,例如"发送朋友圈") → 用
suspend - 操作像 名词 (观察某物,例如"朋友圈动态") → 用
Flow

