zoukankan      html  css  js  c++  java
  • Kotlin的协程

    个人博客

    http://www.milovetingting.cn

    Kotlin的协程

    前言

    本文是Kotlin协程的一个简单笔记,由于刚接触Kotlin语言,如有理解错误,为避免误导别人,可留言评论,以便本人及时修改,感谢各位大佬!关于协程的进阶文章,可参考其它相关资料!

    协程是什么

    协程是一种并发设计模式,在 Android 平台上使用它来简化异步执行的代码。

    以上是官方文档对协程的简单定义。

    下面通过代码来展示协程的具体使用。

    假设有以下的需求:有一个耗时的任务要执行,在执行完成后,需要在主线程刷新UI。

    不使用协程

    在Activity的onCreate中分别调用以下方法

    
    io()
    
    ui()
    
    private fun io() {
            thread {
                Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
                delay(1000)
            }
        }
    
        private fun ui() {
            Log.d(TAG, "ui method,thread:${Thread.currentThread().name}")
        }
    

    输出日志:

    2020-09-25 23:10:25.854 5208-5208/com.wangyz.coroutines D/Coroutine: ui method,thread:main
    2020-09-25 23:10:25.855 5208-5267/com.wangyz.coroutines D/Coroutine: io method,thread:Thread-2
    

    分别调用io()和ui()方法,两个方法分别运行在子线程和主线程中,但是由于子线程的耗时操作,主线程方法先执行了,这样就没有达到我们想要的顺序执行的效果。

    修改代码:

    io2()
    
    private fun io2() {
            thread {
                Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
                delay(1000)
                runOnUiThread {
                    ui2()
                }
            }
        }
    
        private fun ui2() {
            Log.d(TAG, "ui method,thread:${Thread.currentThread().name}")
        }
    

    在子线程中通过runOnUiThread将线程切换到主线程中来,输出结果:

    2020-09-25 23:16:44.753 5597-5641/com.wangyz.coroutines D/Coroutine: io method,thread:Thread-2
    2020-09-25 23:16:45.756 5597-5597/com.wangyz.coroutines D/Coroutine: ui method,thread:main
    

    再来看下协程的实现方式

    使用协程

    依赖项信息

    如需在Android项目中使用协程,需要将以下依赖项添加到应用的 build.gradle 文件中:

    dependencies {
        implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
    }
    

    协程的使用

    GlobalScope.launch(Dispatchers.Main) {
                io3()
                ui3()
            }
    
    private suspend fun io3(){
            withContext(Dispatchers.IO){
                Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
                delay(1000)
            }
        }
    
        private fun ui3() {
            Log.d(TAG, "ui method,thread:${Thread.currentThread().name}")
        }
    

    通过launch方法开启一个协程,通过设置Dispatchers.Main运行在Main线程中,在io3中,通过withContext开启一个线程,并通过设置Dispatchers.IO运行在IO线程。suspend是一个标记,表示这个方法内部会有挂起的操作,它并不会导致线程切换,真正切换线程是通过withContext来切换的。

    输出结果:

    2020-09-25 23:28:19.965 6017-6062/com.wangyz.coroutines D/Coroutine: io method,thread:DefaultDispatcher-worker-1
    2020-09-25 23:28:20.969 6017-6017/com.wangyz.coroutines D/Coroutine: ui method,thread:main
    

    假设我们需要同时请求多个接口,并在这些接口全部返回数据后再统一更新界面,下面用协程来模拟实现这个需求。

    请求多个异步接口

    GlobalScope.launch(Dispatchers.Main) {
                val res1 = async { io4() }
                val res2 = async { io5() }
                val data = res1.await() + res2.await()
                ui4(data)
            }
    
    private suspend fun io4() = withContext(
            Dispatchers.IO
        ) {
            delay(2000)
            Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
            1
        }
    
        private suspend fun io5() = withContext(
            Dispatchers.IO
        ) {
            delay(3000)
            Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
            2
        }
    
        private fun ui4(value: Int) {
            Log.d(TAG, "ui method,thread:${Thread.currentThread().name},result:${value}")
        }
    

    输出结果:

    2020-09-25 23:51:28.161 6495-6536/com.wangyz.coroutines D/Coroutine: io method,thread:DefaultDispatcher-worker-1
    2020-09-25 23:51:29.389 6495-6537/com.wangyz.coroutines D/Coroutine: io method,thread:DefaultDispatcher-worker-2
    2020-09-25 23:51:29.390 6495-6495/com.wangyz.coroutines D/Coroutine: ui method,thread:main,result:3
    

    方法io4执行2秒,方法io5执行3秒,在io5执行完成后,将他们的结果相加再通过ui4更新到UI上。

    参考

    https://developer.android.google.cn/kotlin/coroutines

  • 相关阅读:
    EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之_关于接口调用常见的一些问题(401 Unauthorized)
    EasyNVR H5直播流媒体解决方案前端构建之:如何播放自动适配RTMP/HLS直播播放
    EasyNVR RTSP摄像机转HLS直播服务器中使用Onvif协议控制预置位
    EasyNVR RTSP摄像机HLS直播服务器中使用Onvif协议获取设备快照
    EasyNVR无插件直播服务器如何使用ffmpeg实现摄像机快照功能的
    EasyNVR流媒体服务器接入EasyDSS云视频平台快照上传实现
    EasyDSS RTMP流媒体服务器的HTTP接口query url的C++实现方法
    EasyDSS高性能流媒体服务器前端重构(五)- webpack + vue-router 开发单页面前端实现按需加载
    EasyDSS高性能流媒体服务器前端重构(六)- webpack-dev-server 支持手机端访问
    EasyNVR RTSP转HLS(m3u8+ts)流媒体服务器前端构建之:bootstrap-datepicker日历插件的实时动态展现
  • 原文地址:https://www.cnblogs.com/milovetingting/p/13733256.html
Copyright © 2011-2022 走看看