使用Flow进行多次改装调用



我制作了一个应用程序,用户可以在其中向收藏夹添加服务器(回收行(。它只保存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)
}
}

一切都很好,直到大厅里的收藏夹服务器不再可用,改装呼叫失败。我的问题是:如何在不破坏整个函数的情况下跳过循环中失败的调用。

如果您希望使用RxJava 继续像onResumeText那样的流,请使用emitAll在catch中发出另一个流

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
}
}

最新更新