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