kotlin协程的使用详解

一、协程是什么

协程基于线程,它是轻量级线程。

Kotlin 协程是一种基于 挂起函数(suspend functions) 和 结构化并发(structured concurrency) 的轻量级并发编程模型,允许开发者以接近同步代码的简洁方式编写异步、非阻塞的逻辑。其核心是通过 协作式任务调度(而非抢占式线程切换),在单线程或多线程环境中高效管理并发任务,避免传统线程的资源消耗和复杂性,同时提供直观的错误处理和生命周期管理。

二、协程解决什么问题
  • 处理耗时任务,这种任务常常会阻塞主线程
  • 保证主线程安全,即确保安全地从主线程调用任何suspend函数
三、协程相关依赖配置
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1'

引入的协程版本号,要和依赖的kotlin版本匹配,否者报错

协程依赖对应的版本号:https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-android

四、协程的调度器

所有协程必须在调度器中运行,即使他们在主线程上运行也是如此。

  • Dispatchers.Main Android上的主线程用来处理UI交互和一些轻量级任务。例如1)调用suspend函数 2)调用UI函数 3)更新LiveData
  • Dispatchers.IO 非主线程,转为磁盘和网络IO进行了优化。例如1)数据库 2)文件读写 3)网络处理
  • Dispatchers.Default 非主线程,专为CPU密集型任务进行了优化。1)数组排序 2)JSON数据解析 3)垂差异判断
五、任务泄漏和结构化并发
  • 当协程任务都是,无法追踪,都会导致内存、CPU、磁盘等资源浪费,甚至发送一个无用的网络请求,这种情况称为任务泄漏。
  • 为了避免协程泄漏,Kotlin引入了结构化并发机制。

结构化并发

使用解构化并发可以做到:

  • 取消任务,当某项任务不再需要时取消它
  • 追踪任务,任务正在执行时,追踪它
  • 发出错误信号,协程失败时,发出错误信号表明有错误发生
六、协程作用域(CoroutineScope)
  • 定义协程必须制定其CoroutineScope,它会跟踪所有协程,同样它还可以取消由它启动的所有协程
  • 常用的相关API有:

1)GlobalScope,声明周期是process级别,即使Activity或Fragment已经被销毁,协程任然在执行。
2)MainScope,在Activity中使用,可以在onDestory中取消协程。
3)viewModelScope,只能在ViewModel中使用,绑定ViewModel的生命周期。
4)lifecycleScope,只能在Activity、Fragment中使用,会绑定Activity和Fragment生命周期。

1、MainScope使用

class MainActivity : AppCompatActivity() {private var mainScope = MainScope()override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mainScope.launch(Dispatchers.Main) {
            mainScope.launch(Dispatchers.IO) {
                // 获取网络数据
            }
            // 更新UI
        }
    }
    
    override fun onDestroy() {
        super.onDestroy()
        mainScope.cancel()}
}
-------------------------------------------------------------
// 实现CoroutineScope方式
class MainActivity2 : AppCompatActivity(), CoroutineScope by MainScope() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        val tvRequest = findViewById<TextView>(R.id.tv_Request)
        tvRequest.setOnClickListener {
            launch(Dispatchers.Main) {
                
                launch(Dispatchers.IO) {
                    // 请求数据 
                }
                // 更新UI
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }
}

2、lifecycleScope使用

添加对应的lifecycle和livedata

    // Lifecycle 核心组件
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
    implementation "androidx.lifecycle:lifecycle-common-java8:2.5.1"

    // 可选:LiveData 的扩展(如与 Kotlin Flow 结合)
    implementation "androidx.lifecycle:lifecycle-livedata-core-ktx:2.5.1"
// lifecycleScope是一个与Activity或Fragment的生命周期
// 绑定的特殊CoroutineScope。当UI组件被销毁时,所有在这个范围内启动
// 的协程都会自动取消,防止内存泄漏。
class MainActivity3 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main3)

        // 使用lifecycleScope启动协程
        lifecycleScope.launch(Dispatchers.Main) {
            // 在这里执行协程代码
        }
    }
  }
---------------------------------------------------
// 如果你想更灵活地管理协程,
// 可以创建一个自定义的CoroutineScope并显式地绑定到LifecycleOwner,例如
// ctivity或Fragment
class MainActivity3 : AppCompatActivity() {

    private lateinit var job: Job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main3)

        // 创建一个新的协程作用域
        val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

        // 绑定协程作用域到Activity生命周期
        job = coroutineScope.launch {
            // 在这里执行协程代码
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 取消协程
        job.cancel()
    }
}

3、ViewModel和LiveData使用

如果你正在使用ViewModel和LiveData架构组件,可以在ViewModel中启动协程,并通过LiveData将结果传递给UI层。

class MyViewModel : ViewModel() {
    val resultLiveData = MutableLiveData<String>()
    private val repository = MyRepository()
    fun fetchData() {
        // 在ViewModel中启动协程
        viewModelScope.launch {
            // 从仓库获取数据
            val result = repository.getDataFromApi()
            if (result is Success) {
                // 设置LiveData的值
                resultLiveData.value = result.data
            } else {
                // 处理错误
            }
        }
    }
}

------------------------------------------------------------
/**
 * ViewModel和LiveData
 */
class MainActivity4 : AppCompatActivity() {
    private lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main4)

        // 初始化ViewModel
        viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

        // 观察LiveData的变化
        viewModel.resultLiveData.observe(this, Observer { result ->
            // 更新UI界面

        })

        // 请求数据
        viewModel.fetchData()
    }

}

----------------------------------------------------------------
/**
 * 请求数据
 */
class MyRepository {

    suspend fun getDataFromApi() :Success<String> {
        return Success<String>("")
    }
}

你可能感兴趣的:(kotlin协程的使用详解)