我正试图让我的回收器视图等待,直到我的改造功能完成。改造函数存储在视图模型中,而回收者视图在我的活动中。我可以让它延迟工作,但这似乎不是一个好方法。
GlobalScope.launch {
suspend {
val txt = findViewById<TextView>(R.id.textbox)
viewModel.getStaff()
delay(10000)
withContext(Dispatchers.Main) {
Log.d("coroutineScope", "#runs on ${Thread.currentThread().name}")
createRV(viewModel.pictureList, viewModel.actorList, viewModel.characterList, viewModel.houseList)
}
}.invoke()
这是我的改造函数
suspend fun getStaff(){
val retrofit = Retrofit.Builder()
.baseUrl("http://hp-api.herokuapp.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(HarryPotterApi::class.java)
val call = service.staff()
try {
call.enqueue(object : Callback<Staff> {
override fun onResponse(call: Call<Staff>, response: Response<Staff>) {
if (response.code() == 200) {
val characterData = response.body()!!
pictureList.add(characterData[0].name)
actorList.add(characterData[0].name)
characterList.add(characterData[0].name)
houseList.add(characterData[0].name)
}
}
override fun onFailure(call: Call<Staff>, t: Throwable) {
}
})}catch (e: IOException) {
e.printStackTrace()
}
}
我建议一个更好的方法。而不是delay (10000)
,隐藏recyclerView并使用占位符视图代替
当你准备好显示recyclerView时:
withContext(Dispatchers.Main) {
placeholderView.visibility = View.GONE
recyclerView.visibility = View.VISIBLE
Log.d("coroutineScope", "#runs on ${Thread.currentThread().name}")
createRV(viewModel.pictureList, viewModel.actorList, viewModel.characterList, viewModel.houseList)
}
Retrofit自2.6.0
以来支持协程和挂起函数,因此您不必使用回调,然后以某种方式将异步调用转换为可挂起的(这也是可能的)。你可以使HarryPotterApi.staff()
本身是可挂起的,它们使你的整个代码更简单和同步,同时解决了等待getStaff()
完成的问题。
我没有完整的代码,但我假设HarryPotterApi.staff()
是这样声明的:
fun staff(): Call<Staff>
使其可悬挂:
suspend fun staff(): Staff
然后同步使用:
suspend fun getStaff(){
val retrofit = Retrofit.Builder()
.baseUrl("http://hp-api.herokuapp.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(HarryPotterApi::class.java)
val characterData = service.staff()
pictureList.add(characterData[0].name)
actorList.add(characterData[0].name)
characterList.add(characterData[0].name)
houseList.add(characterData[0].name)
}
这可能不是一个完全工作的例子,但我希望你能明白。
请注意,与您的原始解决方案不同,上面的service.staff()
将在请求失败时抛出异常(感谢@Tenfour04指出这一点)。根据您的需要,您可以捕获它或将其传播到外部代码。像在原始代码中一样,忽略失败似乎不是一个好的解决方案,因为getStaff()
调用之后的代码使用了getStaff()
应该检索的数据。