【问题标题】:How to update a TextView after an API response with Kotlin coroutines?如何在使用 Kotlin 协程的 API 响应后更新 TextView?
【发布时间】:2021-12-09 01:45:49
【问题描述】:

我对 Kotlin、协程和 API 调用完全陌生,我正在尝试基于 this API 制作应用程序。

我的目的是在我的MainActivity 中显示游戏的信息,所以我需要为此填写一些TextView

我的 API 调用和响应系统运行良好:响应正常且没有错误,但是调用是使用 Kotlin 的协程进行的,它不会让我在收到响应后更新我的 UI。

为了简单起见,我只附上我的 MainActivity 代码,这是问题的根源。

class MainActivity : AppCompatActivity() {
    private lateinit var b: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        b = ActivityMainBinding.inflate(layoutInflater)
        setContentView(R.layout.activity_main)
        listAllGames()
    }

    private fun listAllGames() {
        CoroutineScope(Dispatchers.IO).launch {
            val call = getRetrofit().create(APIService::class.java).listAllGames("")
            val games = call.body()
            runOnUiThread {
                if (call.isSuccessful) {
                    b.gameTitle.text = games?.get(0)?.title ?: "Dummy"
                    b.gameDesc.text = games?.get(0)?.short_description ?: "Dummy"
                    b.gameGenre.text = games?.get(0)?.genre ?: "Dummy"
                }
                else {
                    Toast.makeText(applicationContext, "ERROR", Toast.LENGTH_SHORT).show()
                    Log.d("mydebug", "call unsuccessful")
                }
            }
        }
    }

    private fun getRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://www.freetogame.com/api/games/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
}

具体来说,listAllGames() 方法是这里的问题:应用程序将成功构建,如果在 if (call.isSuccessful) 块内添加断点,它将正确显示数据;但是在运行应用程序时,显示将永远保持空白。

提前感谢大家!

【问题讨论】:

    标签: android api kotlin user-interface retrofit2


    【解决方案1】:

    为了使用视图绑定,您需要将膨胀视图从绑定传递到setContentView 方法。否则,您使用绑定来扩展视图,但显示没有绑定的 XML 布局。

    查看文档here

    private lateinit var binding: ResultProfileBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ResultProfileBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
    }
    
    

    (来源:Android Developer documentation - " View Binding Part of Android Jetpack."

    更改您的onCreate 方法如下:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        b = ActivityMainBinding.inflate(layoutInflater)
        setContentView(b.root)
        listAllGames()
    }
    

    【讨论】:

      【解决方案2】:

      另一个答案解释了您对视图的问题,但您也对协程有一些问题。

      • 您应该使用lifecycleScope 而不是创建新范围。 lifecycleScope 会在 Activity 被销毁时(例如在屏幕旋转期间)自动取消自身以避免泄漏 Activity。
      • 您应该使用 Retrofit 的 call.await() 挂起函数,而不是直接阻塞线程并且必须指定调度程序。这还可以让您将内容留在主调度程序上并直接更新 UI,而无需使用 runOnUiThread
          private fun listAllGames() {
              lifecycleScope.launch {
                  val call = getRetrofit().create(APIService::class.java).listAllGames("")
                  try { 
                      val games = call.await()
                      b.gameTitle.text = games?.get(0)?.title ?: "Dummy"
                      b.gameDesc.text = games?.get(0)?.short_description ?: "Dummy"
                      b.gameGenre.text = games?.get(0)?.genre ?: "Dummy"
                  } catch (e: Exception) {
                      Toast.makeText(applicationContext, "ERROR", Toast.LENGTH_SHORT).show()
                      Log.d("mydebug", "call unsuccessful", e)
                  }
              }
          }
      

      实际上,您应该将这样的 API 调用移动到 ViewModel 中,以便它们可以在屏幕旋转期间继续运行。如果这样做,ViewModel 中的函数应该更新 LiveData 或 SharedFlow 而不是 UI 元素。然后你的 Activity 可以观察变化。如果调用启动并旋转屏幕,API 调用将继续运行并仍将其更改发布到新 Activity 的 UI,而无需重新启动。

      【讨论】:

      • 一切正常,但编译器抱怨“未解析的引用”。我正在使用 Retrofit2 v.2.9.0
      • 抱怨哪一段代码?
      • 抱怨 async()!
      • 你的意思是await()?它是一个扩展功能。所以需要从 Call 类中单独导入。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 2021-01-01
      相关资源
      最近更新 更多