RxJava 已老?试试 Kotlin 协程

作者: ImWiki | 来源:发表于2019-09-29 23:42 被阅读0次

    在 Java 时代,RxJava 是 Android 开发非常非常重要的组成,RxJava可以大大降低了我们切换线程的成本。随着 Android 把 Kotlin 作为了第一开发语言,Kotlin 时代已经到来,然而在Kotlin 时代,已经有对线程更好的代替品 协程 Coroutine,他比 RxJava 更加优秀,更加方便操控线程。我们要怀着开放的心态迎接 Kotlin + 协程的到来。

    最简单的协程示例

    引入依赖

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
    

    编写示例代码

    fun main() {
        GlobalScope.launch {
            delay(1000)
            print("World!")
        }
        print("Hello ")
        Thread.sleep(2000)
    }
    

    输出结果

    Hello World!
    
    Android 第一个协程示例

    从前面一个例子,有些人可能有些懵了,这个和我们new 一个线程打印有何区别,从接下来的结合Android主线程的例子,我们就可以清楚协程的工作方式。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            MainScope().launch {
                val startTime = System.currentTimeMillis()
                println("tag1:" + Thread.currentThread().name)
                val text1 = withContext(Dispatchers.IO) {
                    println("tag2:" + Thread.currentThread().name)
                    delay(1000)
                    "Hello "
                }
                val text2 = withContext(Dispatchers.IO) {
                    println("tag3:" + Thread.currentThread().name)
                    delay(1000)
                    "World!"
                }
                println("tag4:" + Thread.currentThread().name)
                println(text1 + text2)
                println("耗时:" + (System.currentTimeMillis() - startTime))
            }
        }
    }
    

    输出结果:

    System.out: tag1:main
    System.out: tag2:DefaultDispatcher-worker-2
    System.out: tag3:DefaultDispatcher-worker-1
    System.out: tag4:main
    System.out: Hello World!
    System.out: 耗时:2031
    

    上面的例子中,我们模拟了两个耗时操作,必须要在异步线程实现处理,处理完成后需要在主线程输出结果,如果不使用协程,上面的实现将变得更加麻烦。

    定义 suspend 挂起方法

    我们对上面的示例进行改进,定义

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            MainScope().launch {
                val startTime = System.currentTimeMillis()
                println("tag1:" + Thread.currentThread().name)
                val text1 = getHello()
                val text2 = getWorld()
                println("tag4:" + Thread.currentThread().name)
                println(text1 + text2)
                println("耗时:" + (System.currentTimeMillis() - startTime))
            }
        }
        private suspend fun getHello(): String {
            return withContext(Dispatchers.IO) {
                println("tag2:" + Thread.currentThread().name)
                delay(1000)
                "Hello "
            }
        }
        private suspend fun getWorld(): String {
            return withContext(Dispatchers.IO) {
                println("tag3:" + Thread.currentThread().name)
                delay(1000)
                "World!"
            }
        }
    }
    

    输出结果

    System.out: tag1:main
    System.out: tag2:DefaultDispatcher-worker-2
    System.out: tag3:DefaultDispatcher-worker-3
    System.out: tag4:main
    System.out: Hello World!
    System.out: 耗时:2032
    
    使用 async 改进上面例子

    使用了 async 关键字意味着,tag2和tag3不是阻塞的,是并行调用的,后面通过 await() 进行结果等待返回,实现原理可以参考 java 线程中的 notify() 和 await() 。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            MainScope().launch {
                val startTime = System.currentTimeMillis()
                println("tag1:" + Thread.currentThread().name)
                val text1 = async { getHello() }
                val text2 = async { getWorld() }
                println("tag4:" + Thread.currentThread().name)
                println(text1.await() + text2.await())
                println("耗时:" + (System.currentTimeMillis() - startTime))
            }
        }
        private suspend fun getHello(): String {
            return withContext(Dispatchers.IO) {
                println("tag2:" + Thread.currentThread().name)
                delay(1000)
                "Hello "
            }
        }
        private suspend fun getWorld(): String {
            return withContext(Dispatchers.IO) {
                println("tag3:" + Thread.currentThread().name)
                delay(1000)
                "World!"
            }
        }
    }
    

    输出结果:

    System.out: tag1:main
    System.out: tag4:main
    System.out: tag2:DefaultDispatcher-worker-1
    System.out: tag3:DefaultDispatcher-worker-3
    System.out: Hello World!
    System.out: 耗时:1070
    

    相关文章

      网友评论

        本文标题:RxJava 已老?试试 Kotlin 协程

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