Skip to content

Instantly share code, notes, and snippets.

@Sukhobrusov
Created October 26, 2021 18:44
Show Gist options
  • Save Sukhobrusov/872f20de1b8f56c501d11131ebcf875a to your computer and use it in GitHub Desktop.
Save Sukhobrusov/872f20de1b8f56c501d11131ebcf875a to your computer and use it in GitHub Desktop.
interface RestApi<Request, Response> {
/**
* Function that will receive [Response] from server and return [Response]
*/
fun obtainResponse(request: Request): Response
}
/**
* [Request] - input data
* [Response] - response dto
* [T] - final result
*/
abstract class RestApiRepository<Request, Response, T> @Inject constructor(
private val restApi: RestApi<Request, Response>
) : NonNullFunction<RestCallback<T>, RestCallback<T>> {
/**
* Function that takes in [Request], converts it to [Response]
* and passes it to [getResult] to return [T].
*
* @param request Input data that will be used to [obtainResponse].
* @return Observable that will pass [RestCallback] to observer
*/
fun getData(
request: Request,
applyScheduler: Scheduler = AndroidSchedulers.mainThread()
): Observable<RestCallback<T>> {
val observable = Observable.create<RestCallback<T>> { emitter ->
emitter.onNext(getLoadingMessage())
try {
val parsedResponse = restApi.obtainResponse(request)
val result = getResult(parsedResponse)
if (emitter.isDisposed.not()) {
emitter.onNext(getSuccessMessage(result))
}
} catch (e: Exception) {
val parsedError = parseExceptionToResult(e) ?: return@create
if (emitter.isDisposed.not()) {
emitter.onNext(parsedError)
}
}
if (emitter.isDisposed.not()) {
emitter.onComplete()
}
}
return observable
.observeOn(applyScheduler)
.concatMap {
Observable.just(apply(it))
}
}
abstract fun getResult(response: Response) : T
abstract fun parseExceptionToResult(exception: Exception): RestCallback.Error<T>?
// methods for testsing observer results
fun getSuccessMessage(result: T): RestCallback.Success<T> {
return RestCallback.Success("Success", result)
}
fun getLoadingMessage(): RestCallback.Loading<T> {
return RestCallback.Loading()
}
}
sealed class RestCallback<T> {
class Success<T>(val message: String,val data: T): RestCallback<T>()
class Error<T>(val errorType: ErrorType): RestCallback<T>()
class Loading<T>: RestCallback<T>()
}
sealed class ErrorType {
object InternetConnectionError: ErrorType()
object TimeOutError: ErrorType()
data class ServerErrorCodeException(val code: Int, val message: String): ErrorType()
data class ParsingException(val exception: Throwable): ErrorType()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment