异步操作未按预期执行 - Kotlin Android
Asynchronous operations not performing as expected- Kotlin Android
我已经编写了一段代码来从 Cloud Firestore 获取数据,并且正在尝试使用协程实现网络调用。我尽量按照官方的指导,但是由于那些文档中的功能不完整,我已经根据自己的要求进行了调整,但这些可能是问题本身。
这是获取数据的函数:
suspend fun fetchHubList(): MutableLiveData<ArrayList<HubModel>> = withContext(Dispatchers.IO) {
val hubList = ArrayList<HubModel>()
val liveHubData = MutableLiveData<ArrayList<HubModel>>()
hubsListCollection.get().addOnSuccessListener { collection ->
if (collection != null) {
Log.d(TAG, "Data fetch successful!")
for (document in collection) {
Log.d(TAG, "the document id is ")
hubList.add(document.toObject(HubModel::class.java))
}
} else {
Log.d(TAG, "No such document")
}
}.addOnFailureListener { exception ->
Log.d(TAG, "get failed with ", exception)
}
if (hubList.isEmpty()) {
Log.d(TAG, "Collection size 0")
} else {
Log.d(TAG, "Collection size not 0")
}
liveHubData.postValue(hubList)
return@withContext liveHubData
}
这里是调用此方法的 ViewModel class:
class HubListViewModel(application: Application): AndroidViewModel(application) {
// The data which will be observed
var hubList = MutableLiveData<ArrayList<HubModel>>()
private val hubListDao = HubListDao()
init {
viewModelScope.launch (Dispatchers.IO){
hubList = hubListDao.fetchHubList()
Log.d(TAG, "Array List fetched")
}
}
}
使用标记消息我知道正在 returned 一个空列表,我从另一个 question of mine 知道这是因为 returned ArrayList 与获取操作,但我不知道为什么,因为我将整个函数包装在 with context
块中。请告诉我为什么 return 和抓取没有按顺序执行。
您应该添加此依赖项 "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.3"
。它允许您使用 await()
替换回调。
suspend fun fetchHubList(): List<HubModel>? = try {
hubsListCollection.get().await().map { document ->
Log.d(TAG, "the document id is ${document.id}")
document.toObject(HubModel::class.java)
}.apply {
Log.d(TAG, "Data fetch successful!")
Log.d(TAG, "Collection size is $size")
}
} catch (e: Exception) {
Log.d(TAG, "get failed with ", e)
null
}
Dispatchers.IO
不是必需的,因为 firebase API 是主安全的
class HubListViewModel(application: Application): AndroidViewModel(application) {
val hubList = MutableLiveData<List<HubModel>>()
private val hubListDao = HubListDao()
init {
viewModelScope.launch {
hubList.value = hubListDao.fetchHubList()
Log.d(TAG, "List fetched")
}
}
}
我已经编写了一段代码来从 Cloud Firestore 获取数据,并且正在尝试使用协程实现网络调用。我尽量按照官方的指导,但是由于那些文档中的功能不完整,我已经根据自己的要求进行了调整,但这些可能是问题本身。
这是获取数据的函数:
suspend fun fetchHubList(): MutableLiveData<ArrayList<HubModel>> = withContext(Dispatchers.IO) {
val hubList = ArrayList<HubModel>()
val liveHubData = MutableLiveData<ArrayList<HubModel>>()
hubsListCollection.get().addOnSuccessListener { collection ->
if (collection != null) {
Log.d(TAG, "Data fetch successful!")
for (document in collection) {
Log.d(TAG, "the document id is ")
hubList.add(document.toObject(HubModel::class.java))
}
} else {
Log.d(TAG, "No such document")
}
}.addOnFailureListener { exception ->
Log.d(TAG, "get failed with ", exception)
}
if (hubList.isEmpty()) {
Log.d(TAG, "Collection size 0")
} else {
Log.d(TAG, "Collection size not 0")
}
liveHubData.postValue(hubList)
return@withContext liveHubData
}
这里是调用此方法的 ViewModel class:
class HubListViewModel(application: Application): AndroidViewModel(application) {
// The data which will be observed
var hubList = MutableLiveData<ArrayList<HubModel>>()
private val hubListDao = HubListDao()
init {
viewModelScope.launch (Dispatchers.IO){
hubList = hubListDao.fetchHubList()
Log.d(TAG, "Array List fetched")
}
}
}
使用标记消息我知道正在 returned 一个空列表,我从另一个 question of mine 知道这是因为 returned ArrayList 与获取操作,但我不知道为什么,因为我将整个函数包装在 with context
块中。请告诉我为什么 return 和抓取没有按顺序执行。
您应该添加此依赖项 "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.3"
。它允许您使用 await()
替换回调。
suspend fun fetchHubList(): List<HubModel>? = try {
hubsListCollection.get().await().map { document ->
Log.d(TAG, "the document id is ${document.id}")
document.toObject(HubModel::class.java)
}.apply {
Log.d(TAG, "Data fetch successful!")
Log.d(TAG, "Collection size is $size")
}
} catch (e: Exception) {
Log.d(TAG, "get failed with ", e)
null
}
Dispatchers.IO
不是必需的,因为 firebase API 是主安全的
class HubListViewModel(application: Application): AndroidViewModel(application) {
val hubList = MutableLiveData<List<HubModel>>()
private val hubListDao = HubListDao()
init {
viewModelScope.launch {
hubList.value = hubListDao.fetchHubList()
Log.d(TAG, "List fetched")
}
}
}