如何使用 Kotlin 协程执行顺序后台任务

如何使用 Kotlin 协程执行顺序后台任务

coroutines-deal-seq-tasks

Kotlin 协程,谁不知道协程!因此,在这篇文章中,我们会讲到其中一个重要的部分,就是制作顺序后台任务。
大家好,我是 Abanoub,在这篇文章中,我将向您展示如何使用async和await以及使用withContext 的另一种方法使用协程来执行顺序后台任务。

顺序意味着如果你有3个任务,第一个任务将运行,第二个任务将在第一个任务完成后执行,第三个任务将在第二个任务完成后执行,依此类推。
1. 添加协程依赖
您需要将 kotlin 协程依赖项添加到您的build.gradle应用程序模块:

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

然后同步你的项目,让我们开始吧。

2. 创建一个CoroutineScope 实例。

这将定义协程将在其中运行的上下文。

val myScope = CoroutineScope(Dispatchers.IO)

3.创建一些后台任务作为挂起函数

 suspend fun doTask1() {
    
    
        repeat(5) {
    
     i ->
            Log.d("CoroutinesTasks", "doTask1: $i")
        }
    }

    suspend fun doTask2() {
    
    
        repeat(5) {
    
     i ->
            Log.d("CoroutinesTasks", "doTask2: $i")
        }
    }

    suspend fun doTask3() {
    
    
        repeat(5) {
    
     i ->
            Log.d("CoroutinesTasks", "doTask3: $i")
        }
    }

现在我们已经创建了三个挂起函数,每个函数将打印一条日志 5 次,这是对后台任务的简单模拟,例如使用 Room 或 Retrofit 制作任务。

4. 使用异步和等待

要按顺序运行这些任务,您可以使用asyncawait函数。async 创建一个新的 Coroutine 并返回一个Deferred对象,而await等待 Coroutine 的结果并返回它的值。

val myScope = CoroutineScope(Dispatchers.IO)
        myScope.launch {
    
    
            Log.d("CoroutinesTasks", "onCreate: Started")

            val result1 = async {
    
     doTask1() }.await()
            val result2 = async {
    
     doTask2() }.await()
            val result3 = async {
    
     doTask3() }.await()

            Log.d("CoroutinesTasks", "onCreate: Ended")
        }

在此示例中,我们使用async按顺序运行每个任务,并使用await等待其结果。这确保了每个任务都按照我们想要的顺序执行,而不会阻塞主线程。

现在,如果你运行这个应用程序,你会看到这样的结果:

  1. 开始执行第一个任务,直到第一个任务完成后才执行第二个任务。
  2. 第一个任务完成,其结果存储在 result1 变量中。
  3. 开始执行第二个任务,直到第二个任务完成后才开始执行第三个任务。
  4. 第二个任务完成,它的结果存储在 result2 变量中。
  5. 开始执行第三个任务,直到第三个任务完成后才开始执行它之后的任何事情。
  6. 第三个任务完成,结果保存在result3变量中。
 D  onCreate: Started
                   D  doTask1: 0
                   D  doTask1: 1
                   D  doTask1: 2
                   D  doTask1: 3
                   D  doTask1: 4
                   D  doTask2: 0
                   D  doTask2: 1
                   D  doTask2: 2
                   D  doTask2: 3
                   D  doTask2: 4
                   D  doTask3: 0
                   D  doTask3: 1
                   D  doTask3: 2
                   D  doTask3: 3
                   D  doTask3: 4
                   D  onCreate: Ended

那么,什么是result1、result2、result3呢?

这些是结果,假设你在第一个任务中从 api 中获得了一个数据列表,那么 result1 将是这个列表,但是 suspend 函数返回类型应该是你想要作为结果获取它的数据,并且在第二个任务中,你会将这个列表保存到数据库中,然后你将它正常传递给第二个任务,我们将在一个例子中解释这一点。

5. 使用withContext()

您也可以使用withContext函数获得相同的结果。

 val myScope = CoroutineScope(Dispatchers.IO)
        myScope.launch {
    
    
            Log.d("CoroutinesTasks", "onCreate: Started")

            val result1 = withContext(Dispatchers.IO) {
    
    
                doTask1()
            }
            val result2 = withContext(Dispatchers.IO) {
    
    
                doTask2()
            }
            val result3 = withContext(Dispatchers.IO) {
    
    
                doTask3()
            }

            Log.d("CoroutinesTasks", "onCreate: Ended")
        }

例子:

将顺序后台任务定义为单独的挂起函数。例如,如果你想执行一个网络请求,然后是数据库访问,你可以定义两个单独的挂起函数:

suspend fun fetchPosts(): List<Post> {
    
    
    // Perform network request
    return myApi.getPosts()
}

suspend fun savePosts(posts: List<Post>) {
    
    
    // Save data to database
    myDao.savePosts(posts)
}

withContext 块中一个接一个地调用顺序后台任务。这将确保每个任务按顺序运行并且不会阻塞 UI 线程。例如:

myScope.launch {
    
    
    val posts = withContext(Dispatchers.IO) {
    
    
        fetchPosts()
    }
    withContext(Dispatchers.IO) {
    
    
        savePosts(posts)
    }
}

本例首先调用fetchPosts进行网络请求,结果保存到posts变量中。然后,使用posts变量作为输入调用savePosts以将帖子保存到数据库中。这两个任务在同一个协程范围内顺序运行。

猜你喜欢

转载自blog.csdn.net/u011897062/article/details/129811742
今日推荐