Search code examples
androidmvvmretrofitrx-javarx-kotlin

Error Handling of Rxjava in mvvm using retrofit


I am calling one api which gives Http status code 400

This is my NetworkBoundResourceNoDb

public abstract class NetworkBoundResourceNoDb<RequestType> {

    private Observable<Resource<RequestType>> result;

    @MainThread
    protected NetworkBoundResourceNoDb() {
        Observable<Resource<RequestType>> source;
        source = createCall()
            .subscribeOn(Schedulers.io())
            .doOnError(t -> onFetchFailed())
            .observeOn(AndroidSchedulers.mainThread());

        result = Observable.ambArray(source);
    }


    public Observable<Resource<RequestType>> getAsObservable() {return result;}

    protected boolean onFetchFailed() {
        return false;
    }


    @NonNull
    @MainThread
    protected abstract Observable<Resource<RequestType>> createCall();
}

This is API code

@GET("api/content/count")
Observable<List<WordCountData>> wordCount();

This is repository Function

    fun wordCount(): Observable<Resource<List<WordCountData>>>? {
    return object : NetworkBoundResourceNoDb<List<WordCountData>>() {

        override fun createCall(): Observable<Resource<List<WordCountData>>> {
            return courseApi.wordCount()
                .flatMap { learntWords ->
                    Observable.just(
                        if (learntWords == null) Resource.error("", emptyList())
                        else Resource.success(learntWords)
                    )
                }
        }

    }.asObservable
}

This is viewmodel Code

private var wordCount = MutableLiveData<Resource<List<WordCountData>>>()

fun getWordCountLiveData() = wordCount

fun getWordCountList() {
    courseRepository.wordCount()?.subscribe { resource -> getWordCountLiveData().postValue(resource) }
}

This is my view code

private fun loadWordCount() {
    crViewModel = ViewModelProviders.of(this, viewModelFactory).get(CrViewModel::class.java)
    crViewModel.getWordCountLiveData().observe(this, androidx.lifecycle.Observer {
        resource -> when {
        resource.isLoading -> println("loading")
        resource.data != null -> {
            drawChart(resource.data)
        }
        else -> handleErrorResponse()
    }
    })
    crViewModel.getWordCountList()
}

I need to pass Http Status code to view. i am able to get the error in onFetchfailed in repository while implementing it with throwable parameter but not able to handle it after that

it gives me "io.reactivex.exceptions.OnErrorNotImplementedException: HTTP 400 " Error

please help me thanks in advance


Solution

  • man, you're asking for many questions in 1.

    fun getWordCountList() {
    courseRepository.wordCount()?.subscribe { resource -> getWordCountLiveData().postValue(resource) }
    }
    

    This is the chunk of code that triggers all of your other network code. However, this lambda only has a success param, not an error param. Add a second lambda, and surround it by paranthesis, in order to account for both success and failure:

    .subscribe({
        successResponse -> // handle success
    }, 
    { error -> // handle error
    })
    

    so, that should take care of at least the "OnErrorNotImplementedException"

    Error 400 usually means that your request is invalid, and/or you're passing the wrong set of parameters to your request. I can't help you there with the amount of info you gave us, and without knowing anything about your server.

    Finally: "I need to pass Http Status code to view". What?? why? Your title even mentions architecture! Why does your view layer even care about the response code from a network call??

    Don't do that. Sure, your view "can" know about the response code, but this is something the view layer should not know about at all.

    I hope this helps.