问题描述
我制作了一个应用,用户可以在其中添加服务器(回收行)。它仅保存IP和端口。然后,当用户打开FavoriteFragment
改造时,每个服务器都会进行呼叫
@GET("v0/server/{ip}/{port}")
suspend fun getServer(
@Path("ip") ip: String,@Path("port") port: Int
): Server
因此,在repository
中,我混合了源并进行了多次呼叫:
suspend fun getFavoriteServersToRecyclerView(): Flow<DataState<List<Server>>> = flow {
emit(DataState.Loading)
try {
val getFavoritesServersNotLiveData = favoritesDao.getFavoritesServersNotLiveData()
val list: MutableList<Server> = mutablelistof()
getFavoritesServersNotLiveData.forEach { fav ->
val server = soldatApiService.getServer(fav.ip,fav.port)
list.add(server)
}
emit(DataState.Success(list))
} catch (e: Exception) {
emit(DataState.Error(e))
}
}
然后在viewmodel
中创建LiveData
对象
fun getFavoriteServers() {
viewmodelScope.launch {
repository.getFavoriteServersToRecyclerView()
.onEach { dataState ->
_favoriteServers.value = dataState
}.launchIn(viewmodelScope)
}
}
一切正常,直到“大厅”和Retrofit呼叫失败中“收藏夹”服务器不再可用为止。 我的问题是:如何在循环中跳过失败的调用而不崩溃整个函数。
解决方法
如果希望继续使用RxJava进行onResumeNext之类的流程,请使用emitAll
发出另一个捕获流。
catch { cause ->
emitAll(flow { emit(DataState.Errorcause)})
}
,
好,我找到了解决方法:
suspend fun getFavoriteServersToRecyclerView(): Flow<DataState<List<Server>>> = flow {
emit(DataState.Loading)
val list: MutableList<Server> = mutableListOf()
try {
val getFavoritesServersNotLiveData = favoritesDao.getFavoritesServersNotLiveData()
val job = CoroutineScope(coroutineContext).launch {
getFavoritesServersNotLiveData.forEach { fav ->
val server = getServer(fav.ip,fav.port)
server.collect { dataState ->
when (dataState) {
is DataState.Loading -> Log.d(TAG,"loading")
is DataState.Error -> Log.d(TAG,dataState.exception.message!!)
is DataState.Success -> {
list.add(dataState.data)
Log.d(TAG,dataState.data.toString())
}
}
}
}
}
job.join()
emit(DataState.Success(list))
} catch (e: Exception) {
emit(DataState.Error(e))
}
}
,
当使用改造时,您可以使用 Response<T>
(从改造导入响应) 包装响应对象,以便
@GET("v0/server/{ip}/{port}")
suspend fun getServer(
@Path("ip") ip: String,@Path("port") port: Int
): Response<Server>
然后在存储库中,您可以在不使用 try-catch
的情况下检查网络是否失败suspend fun getFavoriteServersToRecyclerView(): Flow<DataState<List<Server>>> = flow {
emit(DataState.Loading)
val getFavoritesServersNotLiveData = favoritesDao.getFavoritesServersNotLiveData()
if(getFavoritesServersNotLiveData.isSuccessful) {
val list: MutableList<Server> = mutableListOf()
getFavoritesServersNotLiveData.body().forEach { fav ->
val server = soldatApiService.getServer(fav.ip,fav.port)
// if the above request fails it wont go to the else block
list.add(server)
}
emit(DataState.Success(list))
} else {
val error = getFavoritesServersNotLiveData.errorBody()!!
//do something with error
}
}