Android kotlin实战之协程suspend详解与使用

这篇具有很好参考价值的文章主要介绍了Android kotlin实战之协程suspend详解与使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

        Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言。与许多其他具有类似功能的语言不同,async 与 await 在 Kotlin 中并不是关键字,甚至都不是标准库的一部分。此外,Kotlin 的 挂起函数 概念为异步操作提供了比 future 与 promise 更安全、更不易出错的抽象。

        kotlinx.coroutines 是由 JetBrains 开发的功能丰富的协程库。它包含本指南中涵盖的很多启用高级协程的原语,包括 launch、 async 等等。

 如需了解其他kotlin用法,可查看如下:

Android Kotlin实战之高阶使用泛型扩展协程懒加载详解_蜗牛、Z的博客-CSDN博客

Android kotlin在实战过程问题总结与开发技巧详解_kotlin 同步锁_蜗牛、Z的博客-CSDN博客

Kotlin语法详解与实践教程,区分JAVA以及如何闭坑_kotlin mapof可以嵌套 to_蜗牛、Z的博客-CSDN博客

什么是协程suspend

        suspend的字面含义是暂停、挂起的意思。在kotlin中,代码执行到 suspend 函数的时候会『挂起』,并且这个『挂起』是非阻塞式的,它不会阻塞你当前的线程,挂起的定位: 暂时切走,稍后再切回来,和java的Thread.sleep()不一样,一个是阻塞,一个是等待,类似wait。

阻塞的基本原理一直占用CUP,不让出如果sleep,挂起的是将自己的cup时间让出去,等待重新分配。这样就很好理解了。用最直观的理解是一种异步操作

协程方法的调用

如果当前方法被suspend修饰了,如果不是通过runblock或者coroutines 库调用,那么调用链上的所有函数都要背suspend修饰

1.修饰方法

suspend fun main() {
    delay(1000)
    println("hello")
}

又因为我们在业务中,很难会获取到main方法,所以无法通过main方法在源头解决协程的调用

2.借助工具类

2.1同步方法runBlocking

runBlocking是阻塞调用,如果通过它来处理协程,那么只有当runBlocking的方法体中执行完,才会往下执行,会一直霸占cpu,直到运行完才会释放。

 fun main() {
    runBlocking {
        delay(1000)
        println("hello---block")
    }
    println("hello")
}

Android kotlin实战之协程suspend详解与使用

 2.2异步库kotlinx.coroutines 

异步库的调用是先挂起线程代码,继续执行,等下面执行完才会又回到协程函数执行

fun main() {
    GlobalScope.launch { // 在后台启动一个新的协程并继续
        println("suspend start!") // 在延迟后打印输出
        delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)
        println("suspend end!") // 在延迟后打印输出
    }

    println("sleep start,") // 协程已在等待时主线程还在继续
    Thread.sleep(2000L) // 阻塞主线程 2 秒钟来保证 JVM 存活
    println("sleep end,") // 协程已在等待时主线程还在继续


}

Android kotlin实战之协程suspend详解与使用

 

通过以上日志分析,协程提都不会被执行,被挂起了,先执行了下面的代码,遇到sleep函数,形成阻塞,协程又获取到cpu的时间,开始执行协程代码快,执行完,sleep阻塞完成又继续执行。

coroutines 库的使用

kotlinx.coroutines是填补了kotlin在Java中的缺失,也提供了异步处理协程的问题。

依赖库:

   implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"

使用

1、异步挂起协程

    GlobalScope.launch { // 在后台启动一个新的协程并继续
       
        //协程代码调用处
       
    }

2、延迟

    GlobalScope.launch { // 在后台启动一个新的协程并继续

        delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)

    }

直接调用delay,设置需要阻塞延迟的时间

3、工作对象Job

launch会返回一个对象Job,job就是当前的任务,如果你接受了这个Job,那么代码块将不会执行,需要你手动调用

fun main() {
    val job = GlobalScope.launch { // 启动一个新协程并保持对这个作业的引用
        delay(1000L)
        println("World!")
    }

    println("Hello,")
    runBlocking {
        job.join() // 等待直到子协程执行结束
    }

    
}

job的join只能在阻塞方法中调用,或者suspend方法体,不能在

GlobalScope.launch {
    job.join()
}

调用,否则不会执行当前代码块。因为launch已返回了一个job,当前job没有执行,所以,改job一直处于一个未执行状态。

也可以取消:job.cancel()

 协程作用域:launch{}

GlobalScope与CoroutineScope对比

八股文显示,前者比后者快,通过源码分析,GlobalScope是继承了CoroutineScope,是对CoroutineScope的封装,提供一个静态函数。

结构化的并发

        协程的实际使用还有一些需要改进的地方。 当我们使用 GlobalScope.launch 时,我们会创建一个顶层协程。虽然它很轻量,但它运行时仍会消耗一些内存资源。有一个更好的解决办法。我们可以在代码中使用结构化并发。 我们可以在执行操作所在的指定作用域内启动协程, 而不是像通常使用线程(线程总是全局的)那样在 GlobalScope 中启动.

fun main() = runBlocking { // this: CoroutineScope
    launch { // 在 runBlocking 作用域中启动一个新协程
        delay(1000L)
        println("World!")
    }
    println("Hello,")

 
}

作用域构建器

        除了由不同的构建器提供协程作用域之外,还可以使用 coroutineScope 构建器声明自己的作用域。它会创建一个协程作用域并且在所有已启动子协程执行完毕之前不会结束.

        runBlocking 与 coroutineScope 可能看起来很类似,因为它们都会等待其协程体以及所有子协程结束。 主要区别在于,runBlocking 方法会阻塞当前线程来等待, 而 coroutineScope 只是挂起,会释放底层线程用于其他用途。 由于存在这点差异,runBlocking 是常规函数,而 coroutineScope 是挂起函数

fun main() = runBlocking { // this: CoroutineScope
    launch {
        delay(200L)
        println("Task from runBlocking 1")
    }

    coroutineScope { // 创建一个协程作用域
        launch {
            delay(500L)
            println("Task from nested launch 2")
        }

        delay(100L)
        println("Task from coroutine scope 3") // 这一行会在内嵌 launch 之前输出
    }

    println("Coroutine scope is over 4") // 这一行在内嵌 launch 执行完毕后才输出
}

Android kotlin实战之协程suspend详解与使用

 挂起 :GlobalScope.async

GlobalScope的async异步挂起,支持返回值,且不能单独直接使用,需在runBlocking体内执行。

fun main()= runBlocking {
    println("current thread 1")
    //launch启动后台调度线程,并且不堵塞当前线程
    val deferred = GlobalScope.async {
        println("async thread 2=")
        delay(1000)
        println("async end 3")
        //需要通过标签的方式返回
        return@async "123"
    }
    println("current thread end 4")
    val result = deferred.await()
    println("result 5= $result")
    //当前线程休眠以便调度线程有机会执行
    Thread.sleep(3000)
}

协程上下文与调度器

        协程上下文包含一个 协程调度器 (参见 CoroutineDispatcher)它确定了相关的协程在哪个线程或哪些线程上执行。协程调度器可以将协程限制在一个特定的线程执行,或将它分派到一个线程池,亦或是让它不受限地运行。

launch { // 运行在父协程的上下文中,即 runBlocking 主协程
    println("main runBlocking      : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Unconfined) { // 不受限的——将工作在主线程中
    println("Unconfined            : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Default) { // 将会获取默认调度器
    println("Default               : I'm working in thread ${Thread.currentThread().name}")
}
launch(newSingleThreadContext("MyOwnThread")) { // 将使它获得一个新的线程
    println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
}

调度器类型如下:

public actual object Dispatchers {

    @JvmStatic
    public actual val Default: CoroutineDispatcher = DefaultScheduler


    @JvmStatic
    public actual val Main: MainCoroutineDispatcher get() = MainDispatcherLoader.dispatcher


    @JvmStatic
    public actual val Unconfined: CoroutineDispatcher = kotlinx.coroutines.Unconfined

    @JvmStatic
    public val IO: CoroutineDispatcher = DefaultIoScheduler

    @DelicateCoroutinesApi
    public fun shutdown() {
        DefaultExecutor.shutdown()
        // Also shuts down Dispatchers.IO
        DefaultScheduler.shutdown()
    }
}

调试协程与线程

        协程可以在一个线程上挂起并在其它线程上恢复。 如果没有特殊工具,甚至对于一个单线程的调度器也是难以弄清楚协程在何时何地正在做什么事情。文章来源地址https://www.toymoban.com/news/detail-436271.html

启动方式   

runBlocking 创建新的协程,运行在当前线程上,所以会堵塞当前线程,直到协程体结束
GlobalScope.launch 启动一个新的线程,在新线程上创建运行协程,不堵塞当前线程
GlobalScope.asyn 启动一个新的线程,在新线程上创建运行协程,并且不堵塞当前线程,支持 通过await获取返回值

到了这里,关于Android kotlin实战之协程suspend详解与使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Kotlin 协程初探

    维基百科:协程,英文Coroutine [kəru’tin] (可入厅),是计算机程序的一类组件,推广了协作式多任务的子程序,允许执行被挂起与被恢复。 作为Google钦定的Android开发首选语言Kotlin,协程并不是 Kotlin 提出来的新概念,目前有协程概念的编程语言有Lua语言、Python语言、Go语言

    2024年02月08日
    浏览(45)
  • kotlin协程详解,不可能学不懂

    首先还是先抛出一系列的问题,大家搞清楚这些问题后学习 Kotlin 协程可能会轻松一点: 1、什么是并发?什么是并行? 2、什么是多任务?什么是协作式多任务?什么是抢占式多任务? 3、什么是同步?什么是异步? 4、什么是非阻塞式?什么是阻塞式? 5、什么是挂起? 6、

    2024年02月05日
    浏览(38)
  • Kotlin 协程基础使用学习

    原文: Kotlin 协程基础使用学习-Stars-One的杂货小窝 本篇阅读可能需要以下知识,否则可能阅读会有些困难 客户端开发基础(Android开发或JavaFx开发) Java多线程基础 kotlin基础 本文尽量以使用为主,以代码为辅讲解,不提及过深协程底层代码逻辑,仅做一个基础入门来快速上手学习(断断

    2024年03月18日
    浏览(60)
  • Kotlin 协程 asyn和launch简单使用

    在 Kotlin 协程中, async 和 launch 都是协程构建器,但它们有一些重要的区别: 返回值: launch 函数返回一个 Job 对象,代表一个在后台执行的任务。 Job 可以用于等待任务完成、取消任务等操作。 async 函数返回一个 Deferred 对象,它是 Job 的子接口,并且包含一个计算结果。您可

    2024年01月19日
    浏览(41)
  • Kotlin 协程与生命周期感知组件一起使用

    应用中的每一个 ViewModel 都定义了 ViewModelScope 。如果 ViewModel 已清除,则在此范围内启动的协程都会取消。如果您具有仅在 ViewModel 处于活动的状态时才需要完成的工作。此时协程非常有用。如果要为布局计算某些数据,则应将工作范围限定至 ViewModel ,以便在 ViewModel 清除后,

    2024年02月11日
    浏览(42)
  • Android kotlin序列化之@Parcelize详解与使用

            在Android开发过程中,序列化使用概率一直很高。在页面之间传递的对象,需要要使用序列化,常见的序列化:Parcelable、Serialization。         由于Parcelable在传递压缩比高,效率高,一直被Google官方推荐。在Java语言中,Parcelable可以通过IDE自动生成,但是在kot

    2024年02月08日
    浏览(49)
  • 【28】Kotlin语法进阶——使用协程编写高效的并发程序

    提示:此文章仅作为本人记录日常学习使用,若有存在错误或者不严谨得地方欢迎指正。 协程是Kotlin语言中很有代表性的一种并发设计模式,用于简化异步执行的代码。 协程和线程有点类似,可以简单地将它理解成一种轻量级的线程 。我们前面学习的线程是属于重量级的,

    2024年02月03日
    浏览(53)
  • 大型Android项目架构:基于组件化+模块化+Kotlin+协程+Flow+Retrofit+Jetpack+MVVM架构实现WanAndroid客户端

    前言:苟有恒,何必三更眠五更起;最无益,莫过一日曝十日寒。 之前一直想写个 WanAndroid 项目来巩固自己对 Kotlin+Jetpack+协程 等知识的学习,但是一直没有时间。这里重新行动起来,从项目搭建到完成前前后后用了两个月时间,平常时间比较少,基本上都是只能利用零碎的

    2024年02月09日
    浏览(54)
  • 【kotlin 协程】万字协程 一篇完成kotlin 协程进阶

    Kotlin 中的协程提供了一种全新处理并发的方式,可以在 Android 平台上使用它来简化异步执行的代码。协程是从 Kotlin 1.3 版本开始引入,但这一概念在编程世界诞生的黎明之际就有了,最早使用协程的编程语言可以追溯到 1967 年的 Simula 语言。 在过去几年间,协程这个概念发展

    2024年02月07日
    浏览(52)
  • Kotlin 协程一 —— 协程 Coroutine

    1.1.1基本定义 进程 进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。 进程是资源分配的最小单位,在单核CPU中,同一时刻只有一个程序在内存中被CPU调用运行。 线程 基本的

    2024年02月05日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包