【发布时间】:2022-07-27 17:08:13
【问题描述】:
假设您有一个从您的 Android 应用程序中的远程数据源下载的用户列表,并且由于某种原因您没有本地数据库。然后,此用户列表将在整个应用程序中以多个ViewModels 使用以发出其他网络请求,因此您肯定希望在应用程序存在期间将其缓存并仅在需要时重新获取它。这必然意味着您希望将其缓存在 数据层 中,在我的例子中是 Repository,然后从您的 ViewModels 中获取它。
在像ViewModel 这样的状态持有者中很容易做到 - 只需制作StateFlow 或其他任何东西。但是,如果我们想要在存储库中可用的 List<User> 或 List<User>(在每个 API 请求后缓存在 RAM 中)然后从 UI 层从中收集,该怎么办?实现这一目标的最可测试、稳定和正确的方法是什么?
我最初的想法是这样的:
class UsersRepository @Inject constructor(
private val usersApi: UsersApi,
private val handler: ResponseHandler
) {
private val _usersFlow = MutableStateFlow<Resource<List<UserResponse>>>(Resource.Empty)
val usersFlow = _usersFlow.asStateFlow()
suspend fun fetchUserList() = withContext(Dispatchers.IO) {
_usersFlow.emit(Resource.Loading)
_usersFlow.emit(
handler {
usersApi.getUsers()
}
)
}
}
ResponseHandler 在哪里:
class ResponseHandler {
suspend operator fun <T> invoke(block: suspend () -> T) = try {
Resource.Success(block())
} catch (e: Exception) {
Log.e(javaClass.name, e.toString())
val errorCode = when (e) {
is HttpException -> e.code()
is SocketTimeoutException -> ErrorCodes.SocketTimeOut.code
is UnknownHostException -> ErrorCodes.UnknownHost.code
else -> Int.MAX_VALUE
}
Resource.Error(getErrorMessage(errorCode))
}
}
但是在研究的时候,我在网上发现了一个随机的家伙telling这是错误的:
目前 StateFlow 本质上很热门,因此不建议在存储库中使用。对于冷流和反应流,您可以在 repository 中使用 flow、channelFlow 或 callbackFlow。
他说的对吗?如果是,那么冷流在这种情况下究竟有什么帮助,我们如何妥善管理它们?
如果有帮助,我的 UI 层仅使用 Jetpack Compose 编写
【问题讨论】:
标签: android mvvm repository android-jetpack-compose kotlin-flow