Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@rharter
Created August 19, 2020 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rharter/9e95448a85e2f95b2179e642a748423c to your computer and use it in GitHub Desktop.
Save rharter/9e95448a85e2f95b2179e642a748423c to your computer and use it in GitHub Desktop.
Extension function to convert a store, which emits a stream of **events**, to a repository which emits a stream of **states**. This hides implementation details, like which datasource is providing the data, from consumers.
sealed class Resource<T> {
data class Loading<T>(val data: T? = null, val message: Int? = null) : Resource<T>()
data class Success<T>(val data: T) : Resource<T>()
data class Error<T>(val throwable: Throwable?, val data: T? = null) : Resource<T>()
}
fun <T> Resource<T>.dataOrNull(): T? = when (this) {
is Resource.Loading -> data
is Resource.Success -> data
is Resource.Error -> data
}
fun <T : Any> Flow<StoreResponse<T>>.asRepository(): Flow<Resource<T>> = flow {
var loading = false
var errorResponse: StoreResponse.Error<T>? = null
var data: T? = null
fun <T> StoreResponse.Error<T>.throwable(): Throwable = when (this) {
is StoreResponse.Error.Exception -> error
is StoreResponse.Error.Message -> Throwable(message)
}
suspend fun emitState() {
val error = errorResponse
when {
loading -> emit(Resource.Loading(data))
error != null -> emit(Resource.Error(error.throwable(), data))
else -> emit(Resource.Success(checkNotNull(data)))
}
}
collect {
if (it is StoreResponse.Loading) {
loading = true
} else if (it.origin == ResponseOrigin.Fetcher) {
loading = false
}
if (it is StoreResponse.Error) {
errorResponse = it
} else if (errorResponse?.origin == it.origin) {
errorResponse = null
}
if (it is StoreResponse.Data) {
data = it.value
}
emitState()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment