• 协程(二)——kotlin中协程启动的条件


    上一篇文章介绍了什么是协程,以及协程的作用,优点等,还没了解过的同学,可以去看我上一篇关于协程的文章,链接放在下面

    协程(一)——什么是协程_水很清的博客-CSDN博客

    这篇文章我们来讲协程的使用,简单的使用,毕竟协程是一个很强大的设计模式,深入了解需要花很多的时间,我们先从简单开始,其实学会了简单的使用,基本已经可以满足我们平时的开发需要了,话不多说,开始。

    在开始前,要先贯彻一句话,就是上一篇文章讲到的协程的核心,归纳为一句话就是:

    协程异步就是将耗时的函数标记为suspend,并在协程中调用!不需要开启新线程,不会阻塞UI。

    先看kotlin中协程的简单创建,后面我们再举个例子说明上面的总结。创建前要先了解几个概念

    一、作用域

    协程是通过作用域来创建的,这里有几个常见的作用域,分别是

    GlobalScope - 不推荐使用

    GlobalScope是全局协程,生命周期与Application一样,一般不推荐使用

    runBlocking{} - 主要用于测试 

    runBlocking主要用于测试,开启的协程会阻塞开启协程的线程,这种异步没有意义
    不常用、不推荐!

    MainScope() - 可用于开发

    常用,需要手动停止,这是在应用中最推荐使用的协程使用方式,为自己的组件实现CoroutieScope接口,在需要的地方使用launch{}方法启动协程,在Android中常在Activity\Fragment中使用,缺点是需要手动停止,如果Activity销毁了,忘记手动停止就会造成内容泄漏

    lifecycleScope和viewModelScope

    这两个主要是Android中使用协程,lifecycle对于协程的扩展封装,主要用在Android 开发过程中,我们下一篇讲解在Android中使用协程的时候再讲。

    这里只要明白lifecycleScope主要用于Activity\Fragment中,viewModelScope主要用于viewModel中,并且两者都自动绑定生命周期,不需要手动停止。

    二、讲完了作用域,介绍需要介绍一下调度器

    Dispatchers.Default
    默认的调度器,适合处理后台计算,是一个CPU密集型任务调度器。注意它和IO共享线程池,只不过限制了最大并发数不同。
    Dispatchers.IO
    很显然这是用来执行阻塞 IO 操作的,是和Default共用一个共享的线程池来执行里面的任务。根据同时运行的任务数量,在需要的时候会创建额外的线程,当任务执行完毕后会释放不需要的线程。
    Dispatchers.Unconfined
    由于Dispatchers.Unconfined未定义线程池,所以执行的时候默认在启动线程。遇到第一个挂起点,之后由调用resume的线程决定恢复协程的线程。
    Dispatchers.Main
    指定执行的线程是主线程,在Android上就是UI线程

    调度器其实可以理解为自定运行环境,有点类似与线程,我们指定在IO输入中去做耗时操作,还是切换到主线程操作,类似于这个道理,但是又不是线程的切换。

    三、作用域有了,调度器也有了,还差最后一个,那就是启动方法

    启动方法有两种,分别是

    • launch:启动新协程,launch的返回值为Job,协程的执行结果不会返回给调用方。

    • async:启动新协程,async的返回值为DeferredDeferred继承至Job,可通过调用Deferred::await获取协程的执行结果,其中await是挂起函数。

    看看两者的区别:

    launch(返回Job)与async(返回Deferred)的区别:

    launch启动的协程没有返回结果;async启动的协程有返回结果,该结果可以通过Deferred的await方法获取。
    launch启动的协程有异常会立即抛出;async启动的协程的异常不会立即抛出,会等到调用Deferred::await的时候才将异常抛出。
    async适合于一些并发任务的执行,例如有这样的业务:做两个网络请求,等两个请求都完成后,一起显示请求结果。

    好了,启动条件需要满足的三个条件都已经讲解完了,分别就是作用域、调度器、启动方法,下面看看一个简单启动协程的栗子

    launch方式:

    1. class MainActivity : AppCompatActivity() {
    2. /**
    3. * 使用官方库的 MainScope()获取一个协程作用域用于创建协程
    4. */
    5. private val mScope = MainScope()
    6. override fun onCreate(savedInstanceState: Bundle?) {
    7. super.onCreate(savedInstanceState)
    8. setContentView(R.layout.activity_main)
    9. // 创建一个默认参数的协程,其默认的调度模式为Main 也就是说该协程的线程环境是Main线程
    10. val job1 = mScope.launch {
    11. // 这里就是协程体
    12. // 延迟1000毫秒 delay是一个挂起函数
    13. // 在这1000毫秒内该协程所处的线程不会阻塞
    14. // 协程将线程的执行权交出去,该线程该干嘛干嘛,到时间后会恢复至此继续向下执行
    15. delay(1000)
    16. }
    17. // 创建一个指定了调度模式的协程,该协程的运行线程为IO线程
    18. val job2 = mScope.launch(Dispatchers.IO) {
    19. // 此处是IO线程模式
    20. // 切线程 将协程所处的线程环境切至指定的调度模式Main
    21. withContext(Dispatchers.Main) {
    22. // 现在这里就是Main线程了 可以在此进行UI操作了
    23. }
    24. }
    25. // 下面直接看一个例子: 从网络中获取数据 并更新UI
    26. // 该例子不会阻塞主线程
    27. mScope.launch(Dispatchers.IO) {
    28. // 执行getUserInfo方法时会将线程切至IO去执行
    29. val userInfo = getUserInfo()
    30. // 获取完数据后 切至Main线程进行更新UI
    31. withContext(Dispatchers.Main) {
    32. // 更新UI
    33. }
    34. }
    35. }
    36. /**
    37. * 获取用户信息 该函数模拟IO获取数据
    38. * @return String
    39. */
    40. private suspend fun getUserInfo(): String {
    41. return withContext(Dispatchers.IO) {
    42. delay(2000)
    43. "Kotlin"
    44. }
    45. }
    46. override fun onDestroy() {
    47. super.onDestroy()
    48. // 取消协程 防止协程泄漏 如果使用lifecycleScope则不需要手动取消
    49. mScope.cancel()
    50. }
    51. }

    async方式:主要用于获取返回值和并发

    1. fun asyncTest() {
    2. mScope.launch {
    3. // 开启一个IO模式的线程 并返回一个Deferred,Deferred可以用来获取返回值
    4. // 代码执行到此处时会新开一个协程 然后去执行协程体 父协程的代码会接着往下走
    5. val deferred = async(Dispatchers.IO) {
    6. // 模拟耗时
    7. delay(2000)
    8. // 返回一个值
    9. "Quyunshuo"
    10. }
    11. // 等待async执行完成获取返回值 此处并不会阻塞线程 而是挂起 将线程的执行权交出去
    12. // 等到async的协程体执行完毕后 会恢复协程继续往下执行
    13. val date = deferred.await()
    14. }
    15. }

    以上就是本篇的内容,下一篇讲讲协程在并发上的优势,that's all

  • 相关阅读:
    【算法集训专题攻克篇】第十四篇之栈
    ZZULIOJ1064: 加密字符
    [附源码]计算机毕业设计JAVA“原创音乐爱好者”交流网站论文
    【Android】 屏幕录制screenrecord为什么这么快?
    计算机毕业设计如何做
    kubernetespod控制器详解2与service详解1
    远程直接连接 MySQL 数据库,阿里云腾讯云允许远程连接教程
    电商运营管理——广告系统
    Mysql密码忘记后怎么重置密码,mysql8之后有改动
    Java毕业设计 SSM SpringBoot 水果蔬菜商城
  • 原文地址:https://blog.csdn.net/taoyuxin1314/article/details/126447676