Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity
- import io.reactivex.Completable
- import io.reactivex.Flowable
- import io.reactivex.FlowableTransformer
- import io.reactivex.Observable
- import com.rv.user.networkerrorretrier.Result
- interface NetworkManager {
- /**
- * Exception used to denote that an operation was performed when network was not available.
- */
- class NoNetworkException : IllegalStateException()
- /** @return `true` if is there is an active connection, `false` otherwise.*/
- fun isConnected(): Boolean
- /**
- * @return [Observable] that emits whenever there is change in network connection
- *
- * Note: This observable by default emits item on background thread.
- */
- fun observeConnectivity(): Observable<Connectivity>
- /** @return [Observable] emitting true when there is an active connection, false if otherwise
- *
- * Note: This observable by default emits item on background thread.
- */
- fun observeNetwork(): Observable<Boolean>
- /**
- * @return [Completable] that completes whenever network connection is reestablished again. If the network
- * is available at the time of subscription, then it completes immediately.
- */
- fun awaitOnline(): Completable {
- return observeNetwork()
- .filter { isConnected() }
- .take(1)
- .ignoreElements()
- }
- /**
- * [FlowableTransformer] to handle pre and post execution errors caused for limited network access.
- *
- * 1. Subscribes to `Upstream` directly when network is connected. In case network is
- * not available, waits till network is available and retries task by resubscribing to `Upstream`.
- * 2. Subscription was already in progress but failed due to missing network error, in that case schedule a retry
- * until network is available.
- *
- * During the wait period, the downstream will initially receive a [Result.Failure] with [NoNetworkException]. By handling
- * this exception, you can update UI while the inner upstream waits for network.
- */
- fun <T> networkAwareResultTransformer(): FlowableTransformer<Result<T>, Result<T>> {
- return FlowableTransformer { upstream ->
- // Transform the upstream to handle auto retry in case execution failed due to network error.
- val networkAwareUpstream = upstream
- .switchMap { result ->
- // When we have a Failure case due to no network, schedule a resubscription once network is active
- if (result is Result.Failure && result.isNetworkError()) {
- awaitOnline()
- .andThen(upstream)
- .startWith(result) // Emit error state so UI can know that network error occurred.
- } else {
- // Pass source result as is, we don't care about other states.
- Flowable.just(result)
- }
- }
- return@FlowableTransformer when {
- isConnected() -> networkAwareUpstream // Network is connected, pass networkAwareUpstream to handle post execution errors
- else -> {
- // Emit a Result.Failure<NoNetworkException> initially until network comes back
- val initialNetworkErrorPublisher = upstream
- .take(1) // Take latest result state alone.
- .map {
- Result.Failure(it.unSafeValue(), NoNetworkException())
- }
- awaitOnline() // Delay subscription to emission until network comes back
- .doOnSubscribe {
- println("Waiting for network : $upstream")
- }
- .doOnComplete {
- println("Retrying $upstream after becoming online")
- }
- .andThen(networkAwareUpstream)
- .startWith(initialNetworkErrorPublisher) // Publish initial error state for UI.
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement