Suppose you have a list of users downloaded from a remote data source in your Android application, and for some reason you do not have a local DB. This list of users is then used throughout your entire application in multiple ViewModels to make other network requests, so you would surely like to have it cached for as long as the app lives and re-fetch it only on demand. This necessarily means you want to cache it inside the Data Layer, which is a Repository in my case, to then get it from your ViewModels.
It is easy to do in a state holder like a ViewModel - just make a StateFlow or whatever. But what if we want a Flow of List<User> (that is cached in RAM after every API request) available inside a repository to then collect from it from the UI Layer? What is the most testable, stable and right way of achieving this?
My initial idea led to this:
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()
}
)
}
}
Where ResponseHandler is:
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))
}
}
But while researching I found random guy on the internet telling that it is wrong:
Currently StateFlow is hot in nature so it’s not recommended to use in repository. For cold and reactive stream, you can use flow, channelFlow or callbackFlow in repository.
Is he right? If he is, how exactly do cold flows help in this situation, and how do we properly manage them?
If it helps, my UI Layer is written solely with Jetpack Compose