我對 Kotlin、協程和 API 呼叫完全陌生,我正在嘗試基于此 API制作一個應用程式。
我的目的是在 my 中顯示游戲的資訊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()方法就是這里的問題:app會構建成功,如果在if (call.isSuccessful)block里面加斷點,它會正確顯示資料;但是在運行應用程式時,顯示屏將永遠空白。
提前感謝大家!
uj5u.com熱心網友回復:
為了使用視圖系結,您需要將膨脹的視圖從系結傳遞給setContentView方法。否則,您使用系結來擴展視圖,但顯示沒有系結的 XML 布局。
檢查這里的檔案:
private lateinit var binding: ResultProfileBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
(來源:Android 開發人員檔案 - “查看 Android Jetpack 的系結部分。”)
改變你的onCreate方法如下:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
b = ActivityMainBinding.inflate(layoutInflater)
setContentView(b.root)
listAllGames()
}
uj5u.com熱心網友回復:
另一個答案解釋了您的觀點問題,但您在協程方面也有一些問題。
- 您應該使用
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,而無需重新啟動。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/331766.html
上一篇:過濾器kotlin內的條件最大值
