kotlin-协程(上篇)

首先祝大家端午节快乐,吃粽子了没?哈哈。我今天一直在思考一个问题:端午节是为了纪念屈原老先生投江而在民间流传下来的节日。这本是何等悲壮的一件事,为何时至今日,变成了一个好像很喜庆的日子。屈原老先生估计心想:老子TM只是感动了自己吗?

言归正传,虽然是端午佳节,但是我等屌丝,药不能停。世界一直在变化,要学会拥抱变化。今天想和大家分享的是协程,鄙人才识浅薄,还望诸公海涵。

首先想说的是为什么会有协程的出现?我们来看一下官方给我们的描述:

协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单。

看懂了没?我是没太明白,哈哈。简单的说,协程就是谷歌为了方便异步操作而设计的一套标准流程。为什么要有标准流程,Android开发老油条应该都知道,这么多年来,Android开发的发展史就是一部混乱的历史,从网络请求到数据库再到项目架构,各种技术第三方层出不穷,不同的人又有自己不同的想法,导致项目发展到最后也是处于一个混乱的状态。

谷歌应该也开始意识到这个问题,开始推出了Jetpack。我认为协程和Jetpack有异曲同工之妙。

那么我们该如何使用协程呢?

首先我们需要添加依赖:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:***"

后面三颗星不要直接抄,那是kotlin版本号,我在家也看不了那个基友网站(Github),不知道最新版本是多少了。

依赖添加好了我们来小试牛刀:

我们来看一段代码:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.e("lzy", "主线程id:${mainLooper.thread.id}")
        test()
        Log.e("lzy", "协程执行结束")
    }


    private fun test() = runBlocking {
        repeat(8) {
            Log.e("lzy", "$it 线程id${Thread.currentThread().id}")
            delay(1000)
        }
    }

}

运行一下我们的程序:

2021-06-13 04:51:46.447 5774-5774/com.example.b E/lzy: 主线程id:2
2021-06-13 04:51:46.453 5774-5774/com.example.b E/lzy: 0 线程id2
2021-06-13 04:51:47.456 5774-5774/com.example.b E/lzy: 1 线程id2
2021-06-13 04:51:48.459 5774-5774/com.example.b E/lzy: 2 线程id2
2021-06-13 04:51:49.461 5774-5774/com.example.b E/lzy: 3 线程id2
2021-06-13 04:51:50.462 5774-5774/com.example.b E/lzy: 4 线程id2
2021-06-13 04:51:51.465 5774-5774/com.example.b E/lzy: 5 线程id2
2021-06-13 04:51:52.469 5774-5774/com.example.b E/lzy: 6 线程id2
2021-06-13 04:51:53.471 5774-5774/com.example.b E/lzy: 7 线程id2
2021-06-13 04:51:54.472 5774-5774/com.example.b E/lzy: 协程执行结束

可见,runBlocking启动的协程会阻断当前线程。这种场景显然并不是我们想要的那样。

探索继续,我们再来看一段代码:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val job = GlobalScope.launch {
             delay(6000)
             Log.e("lzy", "协程执行结束")
         }
         Log.e("lzy", "主线程执行结束")
    }

}

运行一下程序:

2021-06-13 04:55:31.597 5957-5957/com.example.b E/lzy: 主线程执行结束
2021-06-13 04:55:37.602 5957-5986/com.example.b E/lzy: 协程执行结束

这两个日志间隔时间为6s。GlobalScope.launch启动的协程并不会阻塞线程。

再介绍一个关键字:suspend。俗称挂起函数。

我们来看一段代码:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch {
            val token = getToken()
            val userInfo = getUserInfo()
            Log.e("lzy", "hello")
        }
        Log.e("lzy", "hi")
    }

    suspend fun getUserInfo() {
        delay(3000)
    }

    suspend fun getToken() {
        delay(3000)
    }


}

运行结果:

2021-06-13 05:04:33.379 6205-6205/com.example.b E/lzy: hi
2021-06-13 05:04:39.392 6205-6234/com.example.b E/lzy: hello

这中间间隔了6s。suspend函数挂起后,协程体内代码不会继续往下执行,且不会阻塞主线程。

这样看来,getToken()方法执行完了之后再去执行getUserInfo()方法,是不是觉得这种方式太老实。就好比单身的屌丝,一次只约一个妹子,等被一个妹子抛弃了再去约另一个妹子,这样子大好年华就这样浪费了是不,哈哈,所以这肯定在某些场景下不是最优解啊。

下面就来个协程的渣男方式,show code:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch {
            val r1 = GlobalScope.async {
                getResult1()
            }
            val r2 = GlobalScope.async {
                getResult2()
            }
            val r = r1.await() + r2.await()
            Log.e("lzy", "$r")
        }
    }

    suspend fun getResult2(): Int {
        delay(4000)
        return 2
    }

    suspend fun getResult1(): Int {
        delay(3000)
        return 1
    }

}

执行结果:

2021-06-13 05:13:53.432 6448-6475/com.example.b E/lzy: 3

async关键字表示并发执行,可以理解为渣男同时约多个妹子,所以得到结果的时间会更快。

值此佳节之际,老夫想吟诗一首:

《辛丑年端午有感》

屈公投江两千载

汨罗之水天上来

粽叶艾草碧又衰

斗转星回无可耐

 

辛丑牛年五月初四笔于姑苏

 

 

 

 

你可能感兴趣的:(kotlin)