I'm trying to force throw an error during the fake downloading using RxJava:
disposable.add(fakeRepo.downloadSomething()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ a: String -> finished() },
{ b: Throwable? -> showError() }
))
fun downloadSomething(): Single<String> {
return Single.just("")
}
I found solutions only with onNext, but I don't want this in my code.
What I should do to invoke showError() ?
Currently I always get finished()
Just use Single.error:
http://reactivex.io/RxJava/javadoc/io/reactivex/Single.html#error-java.lang.Throwable-
public static Single error(Throwable exception)
Returns a Single that invokes a subscriber's onError method when the subscriber subscribes to it.
Related
I've been having troubles with subscribe() method in my code (debug console's message below)
io.reactivex.exceptions.OnErrorNotImplementedException: The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | Expected a string but was BEGIN_OBJECT at line 1 column 2 path $
and I can't figure out how to make it right, there is my part of code where it starts
private fun startSearch(query: String) {
disposables.addAll(IMyService.searchCourse(query)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({ courses ->
adapter = CourseAdapter(baseContext, courses)
recycler_search.adapter = adapter
}, {
Toast.makeText(this, "Not found", Toast.LENGTH_LONG).show()
}))
}
private fun getAllCourses() {
disposables.addAll(IMyService.coursesList
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({ courses ->
adapter = CourseAdapter(baseContext, courses)
recycler_search.adapter = adapter
}, {
Toast.makeText(this, "Not found", Toast.LENGTH_LONG).show()
}))
}
and there is the full code
parameters
In reactive programming, passing a subscriber to an Observable should entail how to deal with three cases:
onSuccess
onError
onFailure
If however, you simply want to pass a subscriber which you know for sure will not have any errors or any failures and certain that it will always succeed, then simply try onSuccess or onFailure as mentioned by #EpicPandaForce. A good practice however is to always implement the three cases as you never know.
In the below code, I am trying to add the body for the .subscribe(). I tried to add the lambda notation but it never worked. Would you please tell me how to implement the .subscribe() method?
Given that, the setupCommRequestService() returns Single<..>
code:
setupCommRequestService()?.
flatMap {
it.getAllPhotos()
.map {
Observable.fromIterable(it)
.map {
it
}
}
.toSortedList()
}
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(
)
There are 4 implementations for subscribe method according Single documentation. In a simple approach, you should implement a strategy for both onSucess and onError. therefor you should use the subscribe method either by passing a BiConsumer or 2 Consumer one for onSucess case and one for onError.
using BiConsumer in lambda:
val disposable = Single.just(1)
.subscribe { success, failure ->
/* whichever is not null */
}
or using 2 Consumer in lambda:
val disposable = Single.just(1)
.subscribe({ success ->
/* success */
}, { failure ->
/* failure */
})
I`m struggling to retry my rxjava Single call after another network call is done in doOnError:
restApi.getStuff()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError {
getRefreshToken(it, AuthenticationManager.Callback{
retry(1)
})
}
.subscribeBy(
onSuccess = { response ->},
onError = { throwable ->}
)
But the retry method cannot be invoked inside the doOnError method.
Do you have any other ideas?
Eventually I used a different approach with creating an Interceptor for token authorization (#Skynet suggestion led me to it).
Here is more info about it:
Refreshing OAuth token using Retrofit without modifying all calls
if you want to check the response and then retry you should try this:
restApi.getStuff()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retryWhen(errors -> errors.flatMap(error -> {
// for some exceptions
if (error instanceof IOException) {
return Observable.just(null);
}
// otherwise
return Observable.error(error);
})
)
otherwise
restApi.getStuff()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry()
from the docs, retry() responds to onError. link
Hi I'm new with RxJava and Kotlin and I loose some concepts about it.
I have "api" like this:
interface VehiclesService {
#GET("/vehicles/")
fun getVehicles(): Single<List<Vehicle>>
}
Then I create the retrofit client, etc.. like this:
var retrofit = RetrofitClient().getInstance()
vehiclesAPI = retrofit!!.create(VehiclesService ::class.java)
finally I do the call:
private fun fetchData() {
compositeDisposable.add(vehiclesAPI .getVehicles()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { vehicles -> displayData(vehicles) }
)
}
And here is where I have the error when I try to launch:
The exception was not handled due to missing onError handler in the subscribe() method call
I know that the error is quite explicit. So I know what is missing, but what I don't know is HOW to handle this error.
I tried adding : .doOnError { error -> Log.d("MainClass",error.message) } but still telling same error message.
You can pass another lambda to subscribe to handle the errors for a specific stream like this:
private fun fetchData() {
compositeDisposable.add(vehiclesAPI .getVehicles()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe( { vehicles -> displayData(vehicles) }, { throwable -> //handle error } )
)
}
P.S: doOnError and other Side Effect operators, will not affect the stream in anyway, they just anticipate the values emitted for side-effect operations like logging for example.
My Question is probably more of the conceptual nature.
I get that by the Observable contract my Observable will not emit any more items after onComplete or onError is called.
But I'm using the RxBindings for Android and therefore it's not "my Observable" but the click on a Button that emits items.
fun observeForgotPasswordButton(): Disposable {
return view.observeForgotPasswordButton()
.flatMap {
authService.forgotPassword(email).toObservable<Any>()
}
.subscribe({
// on next
Timber.d("fun: onNext:")
}, { error ->
// on error
Timber.e(error, "fun: onError")
}, {
// onComplete
Timber.d("fun: onComplete")
})
}
observeForgotPasswordButton() returns an Observable
fun observeForgotPasswordButton(): Observable<Any> = RxView.clicks(b_forgot_password)
The problem is that authService.forgotPassword(email) is a Completable and it will call either onComplete or onError both of which lead to the fact that I cannot reuse the button anymore since the subscription ended.
Is there a way to circumvent this behavior?
Because in an error occurs I would like to be able to retry.
Also I would like it to be possible to send more then one password forgotten emails.
You can use the retry() and repeat() operators to automatically resubscribe to the original Observable (or Completable).
fun observeForgotPasswordButton(): Disposable {
return view.observeForgotPasswordButton()
.flatMap {
authService.forgotPassword(email).toObservable<Any>()
}
.repeat() // automatically resubscribe on completion
.retry() // automatically resubscribe on error
.subscribe({
// on next
Timber.d("fun: onNext:")
}, { error ->
// on error
Timber.e(error, "fun: onError")
}, {
// onComplete
Timber.d("fun: onComplete")
})
}