Created
January 16, 2019 19:38
-
-
Save Groostav/4417c0bf400dadf70a5e5bb61b0dcb36 to your computer and use it in GitHub Desktop.
using coroutines instead of RX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Retrofit.addCallAdapterFactory(ErrorCheckingCallAdapterFactory()) | |
class ErrorCheckingCallAdapterFactory() : CallAdapter.Factory() { | |
override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? { | |
if (CallAdapter.Factory.getRawType(returnType) != Deferred::class.java) { | |
return null // Ignore ~~non-Observable~~ non-coroutine types. | |
} | |
val nextAdapter: CallAdapter<Deferred<???>, ???> = retrofit.nextCallAdapter(this, returnType, annotations) as Deferred<???> | |
return launchAsCallAdapter<???, ???> { next -> | |
val upstreamResult = nextAdapter.adapt(next).await() | |
if (upstreamResult is BaseResponse) { | |
if (!upstreamResult.isSuccessful()) { | |
throw MemErrorException(upstreamResult.result?.retCode, upstreamResult.result?.retMsg, upstreamResult) | |
} | |
} | |
upstreamResult | |
} | |
} | |
} | |
// I would hope somebody smarter with retrofit than me has already written launchAsCallAdaptor, | |
// and they probably gave it a better name (maybe just `adapt { next -> }`??), but heres my shot: | |
fun <TIn, TSth, TOut> CoroutineScope.launchAsCallAdapter(block: suspend (TIn) -> TOut): CallAdapter<TSth, TOut> { | |
val result = object: CallAdaptor<Deferred<TOut>, TIn> { | |
override fun adapt(call: Call<TIn>): Deferred<TOut> = async { | |
block(call.???) | |
// so, does retrofit have a special case for Single.error() such that it will unbox that into an error response for you? | |
// if thats the case, you'd need the same special case code for a failed deferred, | |
// if theres an interface that can be optionally implemented to supply that same metadata, you could implement that here. | |
// ill take a look a little later today... | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Retrofit.addCallAdapterFactory(ErrorCheckingCallAdapterFactory()) | |
class ErrorCheckingCallAdapterFactory() : CallAdapter.Factory() { | |
override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? { | |
if (CallAdapter.Factory.getRawType(returnType) != Single::class.java) { | |
return null // Ignore non-Observable types. | |
} | |
// Look up the next call adapter which would otherwise be used if this one was not present. | |
val delegate = retrofit.nextCallAdapter(this, returnType, | |
annotations) as CallAdapter<Any, Single<*>> | |
return object : CallAdapter<Any, Any> { | |
override fun adapt(call: Call<Any>): Any { | |
// Delegate to get the normal Observable... | |
val startTime = System.currentTimeMillis() | |
val o: Single<*> = delegate.adapt(call) | |
// ...and change it to send notifications to the observer on the specified scheduler. | |
return o.compose(errorCheckTransformer<Any>(startTime)) | |
} | |
override fun responseType(): Type { | |
return delegate.responseType() | |
} | |
} | |
} | |
fun <T> errorCheckTransformer(startTime: Long): SingleTransformer<T, T> { | |
return SingleTransformer { observable -> | |
observable.flatMap { response -> | |
if (response is BaseResponse) { | |
if (!response.isSuccessful()) { | |
return@flatMap Single.error<T>(MemErrorException(response.result?.retCode, response.result?.retMsg, response)) | |
} | |
} | |
Single.just(response) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sorry the types are hard to figure out without an IDE's assistence, and I'll look to see if i can find retrofit special-casing
Single.error
in a bit.