在Android中,如何通过Kotlin协程处理多个API调用

在Android中,如何通过Kotlin协程处理多个API调用

在Android开发中,如何使用Kotlin协程处理多个API调用的示例呢?假设我们已经对Kotlin协程有了一定的了解,包括定义、简单用例和示例等。现在,让我们来看一些真实的Android场景或用例。我们将从一个关于协程作用域的简单问题开始,比如生命周期作用域。

协程问题

问题 #1:如果我们在协程生命周期作用域中运行任何内容而没有提及分发器会发生什么呢?

kotlin 复制代码
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    lifecycleScope.launch {
        val s1 = someTask()
        Log.d(TAG, s1)
    }
}

suspend fun someTask(): String {
    // 我不相信你,给我看看当前线程
    Log.d(TAG, "当前运行的线程 ${Thread.currentThread().name}")
    delay(2000) // 模拟延迟以进行演示
    return "任务的结果"
}

问题 #2

如果它在主线程中运行,那么...

如果我们在协程挂起函数调用之后在作用域外打印一些东西到TextView中会发生什么?

kotlin 复制代码
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    lifecycleScope.launch {
        val s1 = someTask()
        Log.d(TAG, s1)
    }
    binding.myTextView.text = "挂起函数调用之后"
}

问题#3

更复杂一些,我们加一个while循环,那么结果会怎么样呢?会不会导致UI线程出现ANR呢?想要知道答案,请自行运行代码看看结果。

kotlin 复制代码
lifecycleScope.launch {
    val s1 = someTask()
    Log.d(TAG, s1)
}
binding.myTextView.text = "挂起函数调用之后"
while (true) {
    //假设这是模拟UI任务,比如动画或进度旋转,正在进行的UI
    //我们的主线程现在应该始终忙碌
    Log.d(TAG, "我是UI模拟任务")
}

解决方案

用例 #1

我们必须进行两个API调用,第一个API调用将返回一个Auth令牌。然后我们必须使用这个令牌调用第二个API。

简而言之,我们的第二个API依赖于我们第一个API调用的结果。

kotlin 复制代码
lifecycleScope.launch {
    val token  = firstApiCall()
    Log.d(TAG, "token是 $token")
    val result = secondApiCall(token)
    Log.d(TAG, "结果是 $result")
}

suspend fun firstApiCall(): String {
    // 执行API调用1
    delay(2000) // 模拟延迟以进行演示
    return "1234"
}

suspend fun secondApiCall(token: String): String {
    // 执行API调用2
    delay(2000) // 模拟延迟以进行演示
    return "API调用结果 $token"
}

就这样了?是的,就是这样!

但等等!这并不是一个真实的使用ViewModel和MVVM模式进行API调用的示例。

好的,我们来看一些真实的代码。

kt 复制代码
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class TestViewModel: ViewModel() {

    fun secondApiCall() {
        viewModelScope.launch {
            try {
                val token  = getMyToken(isSuccess = true)
                Log.d(TAG, "token is $token")

                //Now make your second API call here using this token
                //repository.getMyData(token)

            } catch (ex: Exception) {

            }
        }
    }

    private suspend fun getMyToken(isSuccess: Boolean): String? {
        val deferred = CompletableDeferred<String?>()
        if (isSuccess) {
            delay(1000)
            deferred.complete("1234")
        } else {
            delay(1000)
            deferred.completeExceptionally(Throwable("Error"))
        }
        return deferred.await()
    }
}

不必进行两次API调用,因为第二次调用依赖于第一次调用!你可以直接调用secondApiCall()函数,它会获取你的令牌。它会等待认证令牌返回,然后使用该令牌调用实际的API。就是这样!

用例 #2

再次,我们必须进行两次API调用,这次我们需要同时获取两个API结果。如果我们只得到一个结果,那么我们无法在UI中显示它,也无法设置RecyclerView Adapter。

kt 复制代码
lifecycleScope.launch {
    //viewModel.secondApiCall()
    val result = firstApiCall()
    val result2 = secondApiCall()
    Log.d(TAG, "$result and $result2")
}

// Assume you have some suspend functions for API calls
suspend fun firstApiCall(): String {
    // Perform API call 1
    delay(2000) // Simulating a delay for demonstration
    return "I am first call"
}

suspend fun secondApiCall(): String {
    // Perform API call 2
    delay(2000) // Simulating a delay for demonstration
    return "I am second call"
}

就这样?并不完全是。因为它们将按顺序运行,也就是同步运行,所以完成这两个调用将需要4秒钟。

现在我们没有任何依赖关系,那么为什么要浪费时间呢?

让我们看看最终优化的代码!

kotlin 复制代码
lifecycleScope.launch {
    val result = async { firstApiCall() }
    val result2 = async { secondApiCall() }

    Log.d(TAG, "${result.await()} and ${result2.await()}")
}

现在你已经节省了2秒钟。请记住,这是每个Android开发者面试都会遇到的一个非常常见的问题。即使他们不问,你也可以提供这些示例来展示你的知识和专业能力。

感谢您的阅读!您可以关注我获取更多信息。

如果您想知道我在哪里,可以查看我的个人资料中的关于部分。

相关推荐
Devil枫1 小时前
Kotlin高级特性深度解析
android·开发语言·kotlin
ChinaDragonDreamer1 小时前
Kotlin:2.1.20 的新特性
android·开发语言·kotlin
雨白12 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹13 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空15 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭16 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日16 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安16 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑17 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟21 小时前
CTF Web的数组巧用
android