赞
踩
1、协程(Coroutine)
协程 就像非常轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂起时不需要阻塞线程,协程是由开发者控制的。所以协程也像用户态的线程,非常轻量级,一个线程中可以创建任意个协程。
协程就像轻量级的线程。线程由系统调度,协程由开发者控制。
kotlin协程 本质上是对线程池的封装
协程通过将线程切换的复杂性封装入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。
2、GlobalScope(不建议使用);
(1)GlobalScope.launch
使用的是DefaultDispatcher,会自动切换到后台线程,不能做UI操作
- GlobalScope.launch {
-
- //GlobalScope开启协程:DefaultDispatcher-worker-1
- Log.d(TAG, "GlobalScope开启协程:" + Thread.currentThread().name)
-
- //子线程中此处不可以做UI操作
- //Toast.makeText(this@MainActivity, "GlobalScope开启协程",Toast.LENGTH_SHORT).show()
-
- }
(2)可以在协程中切换线程
- GlobalScope.launch {
-
- //GlobalScope开启协程:DefaultDispatcher-worker-1
- Log.d(TAG, "GlobalScope开启协程:" + Thread.currentThread().name)
-
- //子线程中此处不可以做UI操作
- //Toast.makeText(this@MainActivity, "GlobalScope开启协程", Toast.LENGTH_SHORT).show()
-
- withContext(Dispatchers.Main){
- Toast.makeText(this@MainActivity, "协程中切换线程", Toast.LENGTH_SHORT).show()
- }
-
- }
(3)GlobalScope.launch(Dispatchers.Main)
通过Dispatchers.Main使协程依托于主线程中,此时可以更新UI等操作。
- GlobalScope.launch(Dispatchers.Main) {
-
- //GlobalScope开启协程:main
- Log.d(TAG, "GlobalScope开启协程:" + Thread.currentThread().name)
-
- //可以做UI操作
- Toast.makeText(this@MainActivity, "GlobalScope开启协程", Toast.LENGTH_SHORT).show()
-
- }
引入方式
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'//lifecycleScope
- implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'//viewModelScope
(1)协程的执行顺序
- private fun test() {
- Log.d(TAG, "test: 方法开始")
- lifecycleScope.launch {
- delay(1000)
- Log.d(TAG, "test: " + Thread.currentThread().name)
- Log.d(TAG, "test: 协程结束")
- Toast.makeText(this@MainActivity, "协程结束", Toast.LENGTH_SHORT).show()
- }
- Log.d(TAG, "test: 方法结束")
- }
日志:
- D/MainActivity: test: 方法开始
- D/MainActivity: test: 方法结束
- D/MainActivity: test: main
- D/MainActivity: test: 协程结束
- private fun test2() {
- lifecycleScope.launch {
- val startTime = System.currentTimeMillis()
- val a = getDataA()
- val b = getDataB()
- val sum = a + b
- //D/MainActivity: test2: sum = 3,耗时:3008
- Log.d(TAG, "test2: sum = $sum,耗时:${System.currentTimeMillis() - startTime}")
- }
- }
-
- private suspend fun getDataA(): Int {
- delay(1000)
- return 1
- }
-
- private suspend fun getDataB(): Int {
- delay(2000)
- return 2
- }
日志:
D/MainActivity: test2: sum = 3,耗时:3008
- private fun test3(){
- lifecycleScope.launch {
- val startTime = System.currentTimeMillis()
- val a = lifecycleScope.async { getDataA() }
- val b = lifecycleScope.async { getDataB() }
- val sum = a.await() + b.await()
- //D/MainActivity: test3: sum = 3,耗时:2009
- Log.d(TAG, "test3: sum = $sum,耗时:${System.currentTimeMillis() - startTime}")
- }
- }
-
- // suspend 协程挂起原理
- // 在编译期,将suspend标记的方法转化成接口回调的方式,本质上还是基于回调实现的。
- private suspend fun getDataA(): Int {
- delay(1000)
- return 1
- }
-
- // 挂起函数,只适用于协程中。
- private suspend fun getDataB(): Int {
- delay(2000)
- return 2
- }
日志:
D/MainActivity: test3: sum = 3,耗时:2009
- private var job: Job? = null
-
- private fun test4() {
- job = lifecycleScope.launch {
- ...
- }
- job?.cancel()
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。