Kotlin之Coroutine

作者: wenson123 | 来源:发表于2018-05-16 16:47 被阅读16次
    1_as86LrhMP7bbf5qsdD38tg.jpeg

    定义

    Coroutine翻译为协程,Google翻译为协同程序,一般也称为轻量级线程,但需要注意的是线程是操作系统里的定义概念,而协程是程序语言实现的一套异步处理的方法。

    在Kotlin文档中,Coroutine定义为一个可被挂起的计算实例

    配置

    build.gradle中dependencies 添加下面2行,注意coroutine目前仍处于experiment阶段,但Kotline官方保证向前兼容。

       dependencies { 
         implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5'      
         implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.19.3"   
     }
    

    实例

    我们看一个简单Android示例:

    activity_coroutine.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".coroutine.CoroutineActivity">
    
        <TextView
            android:id="@+id/tvHello"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </android.support.constraint.ConstraintLayout>
    

    CoroutineActivity.kt

    class CoroutineActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_coroutine)
    
            setup()
        }
    
        fun setup() {
            launch(UI) { // launch coroutine in UI context
                for (i in 10 downTo 1) { // countdown from 10 to 1
                    tvHello.text = "Countdown $i ..." // update text
                    delay(1000) // wait half a second
                }
                tvHello.text = "Done!"
            }
        }
    }
    

    运行程序 tvHello从10倒计时显示到1,最后显示"Done!"

    代码分析:

    我们重点分析setup()函数

    • launch(UI) {...} -----在UIcontext下启动coroutine

    • delay(1000) ----将当前coroutine挂起1秒

    看到这里你可能会疑惑,Android开发中不是禁止在主线程下做延迟或者阻塞操作吗?

    我们回顾下Coroutine的定义:一个可被挂起的计算实例。

    Coroutine不是线程,所以挂起Coroutine不会影响当前线程的运行。

    取消Coroutine运行

    我们修改下上面的代码:

    class CoroutineActivity : AppCompatActivity() {
    
        lateinit  var job:Job
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_coroutine)
    
            setup()
        }
    
        fun setup() {
            job = launch(CommonPool) { // launch coroutine in UI context
                for (i in 10 downTo 1) { // countdown from 10 to 1
                    tvHello.text = "Countdown $i ..." // update text
                    delay(1000) // wait half a second
                }
                tvHello.text = "Done!"
            }
        }
    
        override fun onPause() {
            super.onPause()
    
            job.cancel()
        }
    }
    

    重点是 launch(UI)返回给一个job实例,通过job.cancel()取消coroutine。

    Coroutine和thread关系

    我们再分析下

    launch(UI)
    

    这行代码是指将coroutine指派在UI线程上运行

    当我们运行一段cpu耗时操作时,则需要将coroutine指定在非UI线程上。

    我们写成:

    launch(){...}
    

    这行代码等价于:

    launch(CommonPool){...}
    

    我们分析下CommonPool的实现,发现它会根据当前cpu的核数创建一个线程池提供给Coroutine使用。

        private fun createPlainPool(): ExecutorService {
            val threadId = AtomicInteger()
            return Executors.newFixedThreadPool(defaultParallelism()) {
                Thread(it, "CommonPool-worker-${threadId.incrementAndGet()}").apply { isDaemon = true }
            }
        }
    
        private fun defaultParallelism() = (Runtime.getRuntime().availableProcessors() - 1).coerceAtLeast(1)
    
    

    总结:

    通过上面的分析,我们理解了Coroutine是一个运行在线程上的可被挂起的计算单元实例,对Coroutine的delay,cancel操作不会影响线程的运行,线程的状态变化对我们是透明的,我们不需要关心。

    所以使用Coroutine,可以使我们更加方便得处理异步操作,比如网络请求,数据存储等。

    引用:

    https://github.com/Kotlin/kotlinx.coroutines

    相关文章

      网友评论

        本文标题:Kotlin之Coroutine

        本文链接:https://www.haomeiwen.com/subject/qkxmdftx.html