在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开发者面试都会遇到的一个非常常见的问题。即使他们不问,你也可以提供这些示例来展示你的知识和专业能力。

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

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

相关推荐
一点媛艺3 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风3 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
数据猎手小k6 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小107 小时前
JavaWeb项目-----博客系统
android
风和先行7 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.8 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
似霰9 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶9 小时前
Android——网络请求
android
干一行,爱一行9 小时前
android camera data -> surface 显示
android
断墨先生9 小时前
uniapp—android原生插件开发(3Android真机调试)
android·uni-app