协程(二)——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方式:

 class MainActivity : AppCompatActivity() {

    /**
     * 使用官方库的 MainScope()获取一个协程作用域用于创建协程
     */
    private val mScope = MainScope()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 创建一个默认参数的协程,其默认的调度模式为Main 也就是说该协程的线程环境是Main线程
        val job1 = mScope.launch {
            // 这里就是协程体

            // 延迟1000毫秒  delay是一个挂起函数
            // 在这1000毫秒内该协程所处的线程不会阻塞
            // 协程将线程的执行权交出去,该线程该干嘛干嘛,到时间后会恢复至此继续向下执行
            delay(1000)
        }

        // 创建一个指定了调度模式的协程,该协程的运行线程为IO线程
        val job2 = mScope.launch(Dispatchers.IO) {

            // 此处是IO线程模式

            // 切线程 将协程所处的线程环境切至指定的调度模式Main
            withContext(Dispatchers.Main) {
                // 现在这里就是Main线程了  可以在此进行UI操作了
            }
        }

        // 下面直接看一个例子: 从网络中获取数据  并更新UI
        // 该例子不会阻塞主线程
        mScope.launch(Dispatchers.IO) {
            // 执行getUserInfo方法时会将线程切至IO去执行
            val userInfo = getUserInfo()
            // 获取完数据后 切至Main线程进行更新UI
            withContext(Dispatchers.Main) {
                // 更新UI
            }
        }
    }

    /**
     * 获取用户信息 该函数模拟IO获取数据
     * @return String
     */
    private suspend fun getUserInfo(): String {
        return withContext(Dispatchers.IO) {
            delay(2000)
            "Kotlin"
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 取消协程 防止协程泄漏  如果使用lifecycleScope则不需要手动取消
        mScope.cancel()
    }
}

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

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

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

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值