众所周知,async和launch是启动协程的两种方式。由于我们知道async是用来取回结果的,所以只有当我们需要并行执行时才应该使用&,而launch则是当我们不想取回结果时使用,用于更新等操作我们知道,到目前为止,异步是启动协程并返回结果的唯一方法,但是当我们不想进行并行网络调用时,异步就会出现问题。众所周知,使用async时,需要使用 await ()函数,这会导致主线程阻塞,但是这里引入了withContext的概念,解决了主线程阻塞的问题。
withContext 只是编写异步的另一种方式,无需编写await()。使用 withContext 时,它会串行而不是并行运行任务。因此,应该记住,当我们在后台有一个任务并且想要返回该任务的结果时,我们应该使用 withContext。让我们举一个例子来演示 withContext 的工作原理:
// two kotlin suspend functions // Suppose we have two tasks like below private suspend fun doTaskOne(): String { delay(2000) return "码农乐园" } private suspend fun doTaskTwo(): String { delay(2000) return "kotlin withContext" }
让我们使用 async-await 并行运行这两个任务,然后使用 withcontext 来看看两者之间的区别。
// kotlin function using async fun startLongRunningTaskInParallel() { viewModelScope.launch { val resultOneDeferred = async { TaskOne() } val resultTwoDeferred = async { TaskTwo() } val combinedResult = resultOneDeferred.await() + resultTwoDeferred.await() } }
这里使用异步,两个任务并行运行。现在让我们使用 withContext 并使用withContext连续执行相同的任务。
// kotlin function using withContext fun startLongRunningTaskInParallel() { viewModelScope.launch { val resultOne = withContext(Dispatchers.IO) { TaskOne() } val resultTwo = withContext(Dispatchers.IO) { TaskTwo() } val combinedResult = resultOne + resultTwo } }
这里可以看到,在withContext中一切都是一样的,唯一的区别是这里我们不必使用await ()函数,并且任务是以串行方式执行的。由于这里已经执行了多个任务,因此应该记住 async 应该与多个任务一起使用,而 withContext 应该与单个任务一起使用。现在我们举个例子,尝试详细了解 withContext 以及它是如何执行的;
// sample kotlin program for complete // demonstration of withContext fun testWithContext { var resultOne = "码农乐园" var resultTwo = "testWithContext" Log.i("withContext", "Before") resultOne = withContext(Dispatchers.IO) { function1() } resultTwo = withContext(Dispatchers.IO) { function2() } Log.i("withContext", "After") val resultText = resultOne + resultTwo Log.i("withContext", resultText) } suspend fun function1(): String { delay(1000L) val message = "function1" Log.i("withContext", message) return message } suspend fun function2(): String { delay(100L) val message = "function2" Log.i("withContext", message) return message }