T
T
Tsuzukeru2020-09-12 21:42:04
Java
Tsuzukeru, 2020-09-12 21:42:04

How to properly clean up resources in a nested RxJava request?

Learning to work with RxJava by calling Youtube Api methods.
In order to get information about a video, you need to call 2 methods:
1) searchVideos - to get video identifiers by query string;
2) videoInfo - allows you to get the necessary information about the video by its id;

I write this method:

fun getVideos(query:String){
        activityContract.showProgressBar()
        api.searchVideos(query)
            .doOnError {
                Log.e("searchVideosError",it.message)
                if (it.message.toString() == "HTTP 403 "){
                    activityContract.showErrorDialog("API limit exceeded")
                }
                else {
                    activityContract.showErrorDialog(it.message.toString())
                }
                activityContract.hideProgressBar()
                disposables.dispose()
            }
            .onErrorReturnItem(mutableListOf(Video("ErrorId")))
            .subscribeOn(Schedulers.io())
            .flatMap{ Observable.fromIterable(it)}
            .flatMap {api.videoInfo(it.videoId)}
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnError {
                Log.e("videoInfoError",it.message)
                if (it.message.toString() == "HTTP 403 "){
                    activityContract.showErrorDialog("API limit exceeded")
                }
                else {
                    activityContract.showErrorDialog(it.message.toString())
                }
                activityContract.hideProgressBar()
                disposables.dispose()
            }
            .onErrorReturnItem(Video("ErrorId"))
            .toList()
            .subscribeBy {
                viewModel.saveSearchResults(it)
                activityContract.hideProgressBar()
            }.addTo(disposables)
    }


The code works. I'm interested in two things:
1) Am I clearing the resources correctly? Then 2 methods are called, and in disposables I add only once, at the very end of the method.
2) How to interrupt the further execution of methods in case of an error? In doOnError - I catch a 403 error. If a 403 error occurs, then I call disposables.dispose() and show the fragment with the error. Everything works on the smartphone, but on the emulator there is a further method call and I catch FATAL EXCEPTION.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Denis Zagaevsky, 2020-09-13
@Tsuzukeru

No, everything is very bad, so Rx cannot be used.
Inside the chain, side effects need to be minimized, you have them on any sneeze.
Within the chain, there should be no "resource releases" in the form of disposables.dispose(). dispose should only be outside the chain. Moreover, it is not known what you stuffed into this disposable. One chain failed - and that's it, the work got up completely , because you can’t cram anything else into this disposables. clear() should be called when you need to clear the CompositeDisposable.
.flatMap{ Observable.fromIterable(it)}What kind of nonsense is this anyway? just delete this line and nothing will change.
Usually methods like getVideos return something. In your case it should be Observable/Single.

.onErrorReturnItem(mutableListOf(Video("ErrorId")))
Game. Mutable data in a stream is a road to nowhere. Only immutable. ErrorId? Orly? Make you a sealed class, after all.
Read about SOLID, this method of yours does too many things.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question