2

I'm trying to implement Clean Architecture in my app. My API sends response in success and failure cases as:

{
   "data": [],
   "statusCode": 200,
   "statusMessage": "success",
   "success": true
 }

OR

{
    "statusCode": xxx,
    "statusMessage": "Invalid Details",
    "success": false
  }

In the previous approach I used Retrofit and BaseResponse POJO class to handle the data scenarios, but in my current app I'm using Clean Architecture with RxJava & Retrofit.

I will get one of Observable, Flowable or Single as response but with BaseResponse as type.

data class BaseResponse<T>(
    @SerializedName("status") val status: Boolean,
    @SerializedName("statuscode") val statusCode: Int? = null,
    @SerializedName("message") val message: String? = null,
    @SerializedName("data") val data: T? = null
)

I'm checking Rx Error in Domain using Rx with custom RESULT as success or failure for all:

fun <T> Single<T>.toResult(): Single<Result<T>> = this
.map { Result.Success(it) as Result<T> }
.onErrorReturn {
    Result.Failure(
        if (it is CompositeException) it.exceptions.last().toView()
        else it.toView()
    )
}

but for handling Dynamic Response I'm not able wrap them.

I tried the approach mentioned in How to wrap API responses to handle success and error based on Clean Architecture? and couple of others, but none of them worked out.

How to wrap the items either in usecases / repository or in Data layer and pass them to presentation like data as Result.success or statusMessage as Result.Error

Angela
  • 35
  • 5

1 Answers1

0

if data in your JSON response is null , you can just ignore the <T> in Base Response and can use Either<A, B> custom class in case of Success or failure.

U can create Custom Either as mentioned in here

so in your Repository code looks like

fun getMyList(): Single<Either<BaseModel, CustomModel?>> =
    apiClient.getList()
        .map {
            if (it.status.equals("success")) {
                Either.Success(it.data?.toEntity())
            } else {
                Either.Failure(it.toEntity())
            }
        }

fun <T> BaseResponse<T>.toEntity() = BaseModel(
    status = status,
    statusCode = statusCode,
    message = message
)

Same goes with your CustomResponse.toEntity to CustomModel , However you are doing Single<T>.toResult() so in your Presentation layer , you can check like

.subscribe({ result ->
   when (result) {
     is Result.Success -> result.data.successOrFailure(::hanldeError, ::handleSuccess)
     is Result.Failure -> {}
   }
},{})

and do your operations in hanldeError() and handleSuccess() respectively

GuruCharan
  • 139
  • 1
  • 14