Skip to content

Instantly share code, notes, and snippets.

@mitchtabian
Last active January 23, 2023 17:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mitchtabian/34d03cc9d2183775e9cd3b4bce2545bf to your computer and use it in GitHub Desktop.
Save mitchtabian/34d03cc9d2183775e9cd3b4bce2545bf to your computer and use it in GitHub Desktop.
Starting point for the new NBR class using flows
import com.codingwithmitch.openapi.util.*
import com.codingwithmitch.openapi.util.Constants.Companion.NETWORK_ERROR
import com.codingwithmitch.openapi.util.Constants.Companion.UNKNOWN_ERROR
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
abstract class NetworkBoundResource<NetworkObj, CacheObj, ViewState>
constructor(
private val dispatcher: CoroutineDispatcher,
private val stateEvent: StateEvent,
private val apiCall: suspend () -> NetworkObj?,
private val cacheCall: suspend () -> CacheObj?
)
{
val result: Flow<DataState<ViewState>> = flow{
// ****** STEP 1: VIEW CACHE ******
emitCache(markJobComplete = false)
// ****** STEP 2: MAKE NETWORK CALL, SAVE RESULT TO CACHE ******
val apiResult = safeApiCall(dispatcher){apiCall}
when(apiResult){
is ApiResult.GenericError -> {
emitError(
apiResult.errorMessage?.let { it }?: UNKNOWN_ERROR,
stateEvent
)
}
is ApiResult.NetworkError -> {
emitError(NETWORK_ERROR, stateEvent)
}
is ApiResult.Success -> {
if(apiResult.value == null){
emitError(UNKNOWN_ERROR, stateEvent)
}
else{
updateCache(apiResult.value as NetworkObj)
}
}
}
// ****** STEP 3: VIEW CACHE and MARK JOB COMPLETED ******
emitCache(markJobComplete = true)
}
private fun emitError(message: String, stateEvent: StateEvent?): Flow<DataState<ViewState>> = flow{
emit(
DataState.error(
response = Response(
message = "${stateEvent?.errorInfo()}\n\nReason: ${message}",
uiComponentType = UIComponentType.Dialog(),
messageType = MessageType.Error()
),
stateEvent = stateEvent
)
)
}
private fun emitCache(markJobComplete: Boolean): Flow<DataState<ViewState>> = flow{
val cacheResult = safeCacheCall(dispatcher){cacheCall.invoke()}
var jobCompleteMarker: StateEvent? = null
if(markJobComplete){
jobCompleteMarker = stateEvent
}
emit(
object: CacheResponseHandler<ViewState, CacheObj>(
response = cacheResult,
stateEvent = jobCompleteMarker
) {
override fun handleSuccess(resultObj: CacheObj): DataState<ViewState> {
return handleCacheSuccess()
}
}.result
)
}
abstract fun updateCache(networkObject: NetworkObj)
abstract fun handleCacheSuccess(): DataState<ViewState> // make sure to return null for stateEvent
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment