在菲利普·拉克纳的一篇教程中,他正在进行网络通话和用户界面更改,如下所示:

        lifecycleScope.launchWhenCreated {
        binding.progressBar.isVisible = true
        val response = try {
            RetrofitInstance.api.getTodos()
        } catch(e: IOException) {
            Log.e(TAG, "IOException, you might not have internet connection")
            binding.progressBar.isVisible = false
            return@launchWhenCreated
        } catch (e: HttpException) {
            Log.e(TAG, "HttpException, unexpected response")
            binding.progressBar.isVisible = false
            return@launchWhenCreated
        }
        if(response.isSuccessful && response.body() != null) {
            todoAdapter.todos = response.body()!!
        } else {
            Log.e(TAG, "Response not successful")
        }
        binding.progressBar.isVisible = false
    }

下面是指向他的代码的指针:https://github.com/philipplackner/RetrofitCrashCourse/blob/master/app/src/main/java/com/plcoding/retrofitcrashcourse/MainActivity.kt

默认情况下,lifecycleScope绑定到主线程,这意味着除非我们更改作用域,否则上述代码中的改进网络调用将在主线程上运行.

这一说法正确吗,如果不是为什么?

推荐答案

这有点复杂,但我会试着根据我在翻新代码中发现的情况来解释它.

Yes,您确实是在主调度程序上运行调用RetrofitInstance.api.getTodos()(隐式通过lifecycleScope),但是...

No,您没有在主线程上运行它.在引擎盖下,通过使用suspendCancellableCoroutineenqueue(...) as seen in the source code itself的组合来实现改装中的暂停功能:

suspend fun <T> Call<T>.awaitResponse(): Response<T> {
  return suspendCancellableCoroutine { continuation ->
    continuation.invokeOnCancellation {
      cancel()
    }
    enqueue(object : Callback<T> {
      override fun onResponse(call: Call<T>, response: Response<T>) {
        continuation.resume(response)
      }

      override fun onFailure(call: Call<T>, t: Throwable) {
        continuation.resumeWithException(t)
      }
    })
  }
}

考虑到这一点,enqueue(...)最终将(在兔子洞中的某个地方)在另一个执行器上执行实际的网络请求,因此当您从主调度程序调用它时,它不会导致任何NetworkOnMainThread个违规.为什么?实际上,它并不在主线程上执行任何网络调用.

希望这能澄清一点.:)

Android相关问答推荐

图像在Android Studio中显示,但不在设备中显示

Android开发:主题排版不适用于按钮文本

安卓Gradle看不到dagger 柄

无法使用MenuItemColors.Copy()

有人能帮我在应用程序上使用模拟位置时避免被发现吗?我已经反编译并粘贴了一个代码,S小文件

Hilt+Worker NoSuchMethodException:<;init>;[class android.content.Context,class androidx.work.WorkerParameters]

升级到 Jetpack Compose 物料 list 2023.08.00 需要我将 targetSdk 更改为 34

如何使用 Wea​​r OS 上的运行状况服务模拟位置?

为什么我的 APK 中包含来自旧版 Android 支持库的类?

Jetpack Compose的val变量不能被重新分配

java.lang.ExceptionInInitializerError -- 原因:java.lang.NullPointerException

发布 MAUI 应用程序时出现遇到重复程序集错误

如何使用 Jetpack Compose 在图像上叠加文本

如何在 BottomBar jetpack compose 中删除选定的椭圆项目 colored颜色

为 AlertDialog 的消息文本设置自定义字体

当我更改 ViewModel var 时,Kotlin + Compose 中的 Composable 不会更新

EAS 构建失败,错误代码为 1,但 Expo Build 成功,我需要 EAS 构建来删除未使用的包,如 com.segment.analytics.android:analytics

ObjectBox,如何在冲突中放弃一切迁移?

多个项目 react-native android 构建错误

OpenGLES,为什么 glReadPixels() 不能从 FBO 的 Renderbuffer 的 colored颜色 缓冲区中读取数据?