news 2026/5/15 1:57:04

Jetpack Compose + 协程(Coroutine)完整实战教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Jetpack Compose + 协程(Coroutine)完整实战教程

Jetpack Compose + 协程(Coroutine)完整实战教程

现代 Android 开发里:

Compose + 协程 + Flow

已经是官方主流架构。

如果你只会:

Button(onClick={})

但不会:

  • LaunchedEffect
  • rememberCoroutineScope
  • StateFlow
  • collectAsState
  • Compose 生命周期协程

那基本还没进入真正的 Compose 开发。

这一篇从:原理 → 生命周期 → 实战 → 架构完整讲透。


一、为什么 Compose 特别依赖协程?

因为:

Compose 是:声明式 UI

UI 本身:状态变化 → 自动刷新

而协程非常适合:

  • 异步请求
  • 状态更新
  • Flow 数据流
  • UI 生命周期

所以:Compose 和协程天然契合。


二、Compose 中最重要的协程 API

API作用
LaunchedEffect页面生命周期协程
rememberCoroutineScope手动启动协程
collectAsState收集 Flow
produceState协程转 State
snapshotFlowState 转 Flow

三、LaunchedEffect(最核心)

这是 Compose 协程第一核心


四、第一个 LaunchedEffect

@ComposablefunTestPage(){LaunchedEffect(Unit){delay(2000)println("执行")}}

它是什么?

本质:Compose 生命周期协程

  • 当 Composable 进入界面:自动启动协程
  • 离开界面:自动取消协程

五、为什么不能直接 launch?

很多新人这样写:

@ComposablefunTest(){GlobalScope.launch{// ...}}

这是错误的。

因为:

  • Composable 会频繁重组(Recompose)
  • 可能疯狂创建协程
  • 导致:内存泄漏、重复请求、协程爆炸

六、LaunchedEffect 生命周期

阶段行为
进入 Composition启动协程
离开 Composition取消协程
key 改变重新启动协程

七、key 的作用(非常重要)

LaunchedEffect(userId){loadUser(userId)}

userId变化时:

  • 取消旧协程
  • 启动新协程

八、LaunchedEffect(Unit)

最常见。

LaunchedEffect(Unit)

表示:仅首次进入执行一次,类似Activity.onCreate()


九、Compose 倒计时

@ComposablefunCountDown(){vartimebyremember{mutableStateOf(10)}LaunchedEffect(Unit){while(time>0){delay(1000)time--}}Text("$time")}

为什么 UI 自动刷新?因为mutableStateOf状态变化后,Compose 自动重组 UI。


十、rememberCoroutineScope

第二核心。


十一、为什么需要它?

因为:Button点击时不能直接调用 suspend

错误:

Button(onClick={delay(1000)// onClick 不是 suspend})

十二、正确写法

@ComposablefunTest(){valscope=rememberCoroutineScope()Button(onClick={scope.launch{delay(1000)println("点击")}}){Text("按钮")}}

十三、rememberCoroutineScope 本质

它返回与当前 Composition 绑定的 CoroutineScope,页面销毁自动 cancel。


十四、LaunchedEffect vs rememberCoroutineScope

这是高频面试题。

LaunchedEffectrememberCoroutineScope
适合:自动执行任务适合:用户事件触发
页面初始化Button 点击
自动请求手势事件
倒计时Snackbar
Flow 收集

十五、Compose + ViewModel

现代 Android 标准方案。

ViewModel

classUserViewModel:ViewModel(){varuserbymutableStateOf<User?>(null)privatesetfunloadUser(){viewModelScope.launch{user=api.getUser()}}}

Compose

@ComposablefunUserPage(vm:UserViewModel=viewModel()){LaunchedEffect(Unit){vm.loadUser()}Text(vm.user?.name?:"")}

为什么不用 lifecycleScope?

  • Compose 推荐ViewModelScope
  • UI 只负责显示状态

十六、Compose + StateFlow(现代官方方案)

这是最重要的。

ViewModel

classUserViewModel:ViewModel(){privateval_uiState=MutableStateFlow<User?>(null)valuiState=_uiState.asStateFlow()funload(){viewModelScope.launch{_uiState.value=api.getUser()}}}

Compose 收集 Flow

@ComposablefunUserPage(vm:UserViewModel=viewModel()){valuserbyvm.uiState.collectAsState()Text(user?.name?:"")}

十七、collectAsState 本质

它将Flow → Compose State,当 Flow 发射新数据,自动重组 UI。


十八、完整执行流程(最重要)

ViewModelScope ↓ 网络请求 ↓ StateFlow更新 ↓ collectAsState收到 ↓ Compose自动重组 ↓ UI刷新

这就是:现代 Android UI 响应式架构


十九、Compose + Retrofit + 协程

完整现代写法。

Repository

classUserRepository{suspendfungetUser()=api.getUser()}

ViewModel

classUserViewModel:ViewModel(){privatevalrepository=UserRepository()varuserbymutableStateOf<User?>(null)privatesetfunloadUser(){viewModelScope.launch{user=repository.getUser()}}}

Compose UI

@ComposablefunUserScreen(vm:UserViewModel=viewModel()){LaunchedEffect(Unit){vm.loadUser()}Text(vm.user?.name?:"")}

二十、为什么不在 Compose 直接请求网络?

错误:

LaunchedEffect(Unit){api.getUser()}

因为:UI 不应该直接操作数据层,否则不好测试、生命周期混乱、逻辑耦合


二十一、Compose 中的协程取消

Compose 生命周期结束,自动 cancel

例如LaunchedEffect离开页面,协程自动结束。


二十二、rememberUpdatedState(高级)

经典问题:LaunchedEffect 内拿到旧值。

vallatestCallbackbyrememberUpdatedState(onClick)

作用:始终拿到最新 lambda,避免闭包旧引用问题。


二十三、produceState

作用:协程 → State

valuserbyproduceState<User?>(null){value=api.getUser()}

本质:内部其实就是LaunchedEffect + mutableStateOf


二十四、snapshotFlow

作用:Compose State → Flow

snapshotFlow{text}.collect{// ...}

适合:搜索监听、输入变化、滚动监听。


二十五、Compose 搜索防抖(经典实战)

ViewModel

classSearchViewModel:ViewModel(){valkeyword=MutableStateFlow("")init{viewModelScope.launch{keyword.debounce(500).collect{search(it)}}}}

Compose

TextField(value=text,onValueChange={text=it vm.keyword.value=it})

二十六、Snackbar 协程

这是rememberCoroutineScope高频场景。

valsnackbarHostState=remember{SnackbarHostState()}valscope=rememberCoroutineScope()Button(onClick={scope.launch{snackbarHostState.showSnackbar("成功")}}){}

二十七、Compose 动画为什么也用协程?

Compose 动画很多本质也是 suspend。例如:

Animatable.animateTo()

内部:协程驱动帧刷新


二十八、Compose 中常见错误

错误说明
在 Composable 直接GlobalScope.launch生命周期不可控
重组导致重复请求api.getUser()直接写在 UI
collect没有生命周期flow.collect可能泄漏

二十九、正确的 Flow 收集

推荐:collectAsState()

或者:collectAsStateWithLifecycle()(官方推荐)


三十、collectAsStateWithLifecycle

implementation"androidx.lifecycle:lifecycle-runtime-compose"
valuiStatebyvm.uiState.collectAsStateWithLifecycle()

为什么推荐它?自动处理生命周期,页面不可见自动暂停收集。


三十一、Compose + Room + Flow

现代数据库方案。

DAO

@Query("SELECT * FROM user")fungetUsers():Flow<List<User>>

Compose

valusersbydao.getUsers().collectAsState(initial=emptyList())

数据库变化,UI 自动刷新。


三十二、Compose + Paging3 + 协程

现代列表方案。

ViewModel

Pager(...).flow.cachedIn(viewModelScope)

Compose

collectAsLazyPagingItems()

三十三、Compose 协程源码核心

最核心:

  • Recomposer
  • CoroutineScope
  • MonotonicFrameClock

Compose 本质:也是协程驱动。


三十四、Compose 为什么不卡 UI?

因为:

  • suspend不阻塞线程
  • Recomposer分帧执行
  • 状态驱动刷新

三十五、Compose 协程面试题

1. LaunchedEffect 和 rememberCoroutineScope 区别?

API用途
LaunchedEffect自动生命周期任务
rememberCoroutineScope用户事件协程

2. collectAsState 本质?

Flow → State

3. Compose 为什么容易重复请求?

因为:重组(Recomposition)

4. 为什么不用 GlobalScope?

因为:生命周期不可控

5. Compose 官方推荐状态方案?

StateFlow+collectAsStateWithLifecycle


三十六、现代 Compose 最佳架构(企业级)

Compose UI ↓ ViewModel ↓ StateFlow ↓ Repository ↓ Retrofit / Room

三十七、真正理解 Compose + 协程

Compose 真正核心:UI = State 的函数

而协程负责:异步修改 State

最终:State变化 → Compose自动重组 → UI自动刷新

这就是现代 Android 的本质。


三十八、真正的大脑模型(最重要)

看到LaunchedEffect,自动想到:

Composition生命周期 + CoroutineScope + 自动取消

看到collectAsState(),自动想到:

Flow → State → Recomposition

看到viewModelScope.launch,自动想到:

协程 → 更新StateFlow → Compose刷新UI

三十九、最后一句(Compose 为什么这么强)

传统 AndroidCompose
手动找View状态驱动UI
手动刷新UI协程驱动异步
手动管理生命周期Flow驱动数据流

这就是Google 现在整个 Android UI 架构的核心方向。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 1:56:04

2026年,靠谱口碑佳的FPC大尺寸激光切割机企业

在2026年&#xff0c;电子制造行业对FPC&#xff08;柔性电路板&#xff09;大尺寸激光切割机的需求持续增长。选择一家靠谱且口碑佳的企业至关重要&#xff0c;深圳达尔成智能科技有限公司&#xff08;DELLSON&#xff09;就是这样一家值得关注的企业。一、应用范围广泛DELLSO…

作者头像 李华
网站建设 2026/5/15 1:50:27

KPZ标度律的跨域同构映射研究(世毫九实验室原创研究)

KPZ标度律的跨域同构映射研究&#xff08;世毫九实验室原创研究&#xff09; 作者&#xff1a;方见华 单位&#xff1a;世毫九实验室 摘要 本研究基于2026年德国团队在《Science》期刊发表的二维KPZ普适性验证这一突破性成果&#xff0c;提出了"KPZ标度律的跨域同构映射研…

作者头像 李华
网站建设 2026/5/15 1:49:03

ESP32物联网网关开发实战:从硬件选型到实时控制协议设计

1. 项目概述&#xff1a;一个连接物理世界与数字世界的“桥梁”最近在折腾一个挺有意思的项目&#xff0c;名字叫openclaw-esp32-bridge。光看这个仓库名&#xff0c;就能嗅到一股浓浓的“硬核”和“连接”的味道。openclaw听起来像是一个开源的控制或抓取系统&#xff0c;而es…

作者头像 李华
网站建设 2026/5/15 1:43:21

Webhook专用轻量级数据库whodb:内存存储与高性能事件处理实践

1. 项目概述&#xff1a;一个为Webhook而生的轻量级数据库如果你正在开发一个需要处理Webhook的后端服务&#xff0c;或者正在构建一个需要快速存储和查询事件数据的应用&#xff0c;那么你很可能已经体会过传统数据库在这种场景下的“笨重感”。无论是启动一个MySQL实例&#…

作者头像 李华
网站建设 2026/5/15 1:42:47

脉冲Transformer硬件加速器设计与优化实践

1. 脉冲Transformer硬件加速器设计背景脉冲神经网络&#xff08;SNN&#xff09;近年来成为深度学习领域备受关注的研究方向&#xff0c;它通过模拟生物神经元的脉冲发放机制&#xff0c;实现了事件驱动的异步计算。与传统人工神经网络&#xff08;ANN&#xff09;相比&#xf…

作者头像 李华