欢迎来到徐庆高(Tea)的个人博客网站
磨难很爱我,一度将我连根拔起。从惊慌失措到心力交瘁,我孤身一人,但并不孤独无依。依赖那些依赖我的人,信任那些信任我的人,帮助那些给予我帮助的人。如果我愿意,可以分裂成无数面镜子,让他们看见我,就像看见自己。察言观色和模仿学习是我的领域。像每个深受创伤的人那样,最终,我学会了随遇而安。
当前位置: 日志文章 > 详细内容

Android协程高级用法大全

2025年08月19日 Android
这里系统梳理一下android/kotlin 协程的一些高级用法。会从上下文管理、作用域控制、异常处理、性能优化、异步组合等角度讲解,给你落地可用的示例。1️⃣ 协程作用域(coroutinescop

这里系统梳理一下 android/kotlin 协程 的一些高级用法。会从 上下文管理、作用域控制、异常处理、性能优化、异步组合 等角度讲解,给你落地可用的示例。

1️⃣ 协程作用域(coroutinescope)与生命周期绑定

在 android 中,协程最好绑定到 生命周期,避免内存泄漏。

activity/fragment 中

class mainactivity : appcompatactivity() {
    // 生命周期感知协程作用域
    private val scope = lifecyclescope
    override fun oncreate(savedinstancestate: bundle?) {
        super.oncreate(savedinstancestate)
        scope.launch {
            val data = fetchdata()
            updateui(data)
        }
    }
}
  • lifecyclescope:绑定 activity/fragment 生命周期,自动取消
  • viewmodelscope:绑定 viewmodel 生命周期

手动创建 coroutinescope

private val customscope = coroutinescope(dispatchers.io + supervisorjob())
  • 可以用 supervisorjob() 避免一个子协程失败影响其它子协程
  • 记得在 ondestroy() 或 oncleared() 时 customscope.cancel()

2️⃣ 异步组合:并发和串行

串行执行

val result1 = async { fetchdata1() }.await()
val result2 = async { fetchdata2() }.await()
val finalresult = combine(result1, result2)
  • 按顺序等待,每个任务完成后再执行下一个

并行执行

val deferred1 = async { fetchdata1() }
val deferred2 = async { fetchdata2() }
val result1 = deferred1.await()
val result2 = deferred2.await()
  • 并行启动,节省等待时间

并行 + awaitall

val results = awaitall(
    async { fetchdata1() },
    async { fetchdata2() },
    async { fetchdata3() }
)

3️⃣ 异常处理与结构化并发

try-catch

scope.launch {
    try {
        val result = fetchdata()
    } catch (e: ioexception) {
        handleerror(e)
    }
}

coroutineexceptionhandler

val handler = coroutineexceptionhandler { _, exception ->
    log.e("coroutine", "caught $exception")
}
scope.launch(handler) {
    val result = fetchdata()
}

supervisorjob

  • 父协程失败不影响子协程
val supervisor = supervisorjob()
val scope = coroutinescope(dispatchers.io + supervisor)

4️⃣ 切换线程/调度器

  • dispatchers.main → ui 操作
  • dispatchers.io → 网络/文件操作
  • dispatchers.default → cpu 密集型计算
scope.launch(dispatchers.io) {
    val data = fetchdata()
    withcontext(dispatchers.main) {
        updateui(data)
    }
}

usewithcontext替代launch切换线程

  • 便于返回值,避免嵌套 launch

5️⃣ 超时与取消

超时

try {
    withtimeout(3000l) {
        fetchdata()
    }
} catch (e: timeoutcancellationexception) {
    log.e("coroutine", "timeout")
}

取消

val job = scope.launch {
    fetchdata()
}
job.cancel() // 立即取消

可取消挂起函数

  • 网络、延迟、channel 等挂起函数是可取消的
  • cpu 密集型循环需要手动检查 isactive
for (i in 1..1000) {
    if (!isactive) break
    dowork()
}

6️⃣ channels 与 flow(响应式数据流)

channel

  • 类似队列,生产者和消费者解耦
val channel = channel<int>()
scope.launch {
    for (i in 1..5) channel.send(i)
    channel.close()
}
scope.launch {
    for (i in channel) {
        println(i)
    }
}

flow

  • kotlin 原生的冷流,支持各种操作符
fun fetchnumbers(): flow<int> = flow {
    for (i in 1..5) {
        delay(100)
        emit(i)
    }
}
scope.launch {
    fetchnumbers()
        .map { it * 2 }
        .filter { it > 5 }
        .collect { println(it) }
}

7️⃣ 高级技巧

  • 组合多个异步源
val flow1 = flow { emit(fetchdata1()) }
val flow2 = flow { emit(fetchdata2()) }
flow1.combine(flow2) { d1, d2 -> d1 + d2 }
    .collect { println(it) }
  • 懒启动的 async
val deferred = async(start = coroutinestart.lazy) { fetchdata() }
deferred.await() // 真正开始执行
  • 异常隔离
    • 使用 supervisorjob() 避免一个子协程挂掉影响整个父协程

到此这篇关于android协程的用法大全的文章就介绍到这了,更多相关android协程用法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!