Debuggers break-point does not hit when I do network request, even though network request is sent.
Calling from ViewModel
Here:
fun getData(): Single<ArrayList<Data>> {
return service.getData()
.map { jsonApiObject ->
val x: ArrayList<Data> = ArrayList() /*Breakpoint is here*/
return#map x
}
}
Well, the break-point should hit whenever I call this function, but it does not. When I log request with interceptor, I can see that the request link is correct and response code is 200 with correct data. What could cause this? I tried to rebuild project/invalidate cache.
Even if I had wrong gson converter configuration set up with retrofit2, theoretically I still should get till the break point and only when using gson builder object, only then get an error, right?
[![enter image description here][1]][1]
FOUND THE REASON:
Whenever I .addConverterFactory(
JSONConverterFactory.create(...::class.java)) debugger will stop inside map block, but if I do .addConverterFactory(GsonConverterFactory.create()) it will not. Why?
Try adding Debug.waitForDebugger() before the line where you want to have the breakpoint.
Related
I am using the below code in an Android project to load data from the database(cache) and from API request:
Observable.concatArrayEagerDelayError(
getDatabaseData(),
getRemoteData()
).debounce(400, TimeUnit.MILLISECONDS)
Both returns from getDatabaseData() and getRemoteData() are Observable<MyObj>
It looks like is working as expected, except when an error occurs while trying to get the remote data.
On the subscriber, I receive just the onError callback, so the cached data is not available to be handled and displayed.
I tried changing to concatArray and concat, but it has the same issue.
Any possible solution to this problem?
The problem is that the error will push out the database value in debounce thus it is never delivered. If one materializes the flow, then the error notification will do the same.
The best I can think of is to shift the error beyond the debounce timer thus you get the succeeding item at least:
Observable.concatArrayEagerDelayError(
Observable.just(1).delay(100, TimeUnit.MILLISECONDS),
Observable.<Integer>error(new IOException()).delay(200, TimeUnit.MILLISECONDS, true)
)
.onErrorResumeNext((Function<Throwable, Observable<Integer>>)(error ->
Observable.<Integer>error(error).delay(500, TimeUnit.MILLISECONDS, true))
)
.doOnEach(System.out::println)
.debounce(400, TimeUnit.MILLISECONDS)
.blockingSubscribe(
System.out::println,
Throwable::printStackTrace
);
fun remove(data: String): Single<JSONApiObject> {
return service.remove(data)
.onErrorResumeNext(ErrorHandler(ErrorParser()))
}
Is onErrorResumeNext necessary, if I don't intend to do anything onError? This is a POST request.
No. But it recommendable to implement the onError or onErrorResumeNext in order to handle whenever your subscription goes wrong. Otherwise, your program will crash.
For example, in your case, if your POST request fails you can make know your user that is caused by a network disconnection, fields missing or if the server is down.
I have the following requirement:
Multiple observers (fragments) need to subscribe to a data source.
Activity will start a network request. Once the request is successful, each observer will receive the result.
I've trying to do it using cache / publish operators, but the issue is when initial request returns an error. At this point I wish to reset the stream and subsequent calls to the method should run a new network request instead of returning an error each time.
Here's what I have currently.
private Flowable<List<Data>> dataObservable;
private Flowable<List<Data>> getData(){
if(dataObservable == null){
dataObservable = apiService.getData()
.doOnError(throwable -> {
dataObservable = null;
})
.cache();
}
return dataObservable;
}
This works, but the code feels wrong. There's got to be a better way.
You can define the observable ahead of time, and it won't actually do anything until something subscribes to it. That's one less null value to worry about.
You can use the retry() operator, or a variant of it, to automatically retry the network operation on an error.
Finally, the cache() operator will ensure that only one network connection subscription is active. Each subscriber will get any updates from the observable, and will be oblivious to any network errors experienced.
Flowable<List<Data>> dataObservable = apiService.getData()
.retry()
.cache();
Apparently there is no operator for that.
The issue was discussed at Observable, retry on error and cache only if completed
and Plato created a nice tiny lib for that
platoblm/rx-onerror-retry-cache.
I am working on network module where it should provide offline data where I am fetching previously stored JSON response from local db and building response and returning to the application. All this is happening in my okhttp Interceptor at application level. I know I could have checked for n/w availability with ConnectivityManager
Every time I tried with n/w disabled or changing server false server URL for testing, Debugger just disappears call to chain.proceed(request)
Please note I knew I would have landed in onFaluire of retrofit in my app for any internet error. but I don't want that. Instead I want that to be handled inside interceptor and build response and return.
Searched on net found one question similar to this.
Let me know if any clarity needed on this.
I know this is very old post, but for those like me that also encounter this problem here's what I found.
The chain.proceed(request) call will throw an exception so any codes below this call won't be executed.
So if you really want to execute a codes when an exception occurred you may wrap the chain.proceed() call with try-catch.
override fun intercept(chain: Interceptor.Chain): Response {
try {
val response = chain.proceed(chain.request())
return response
} catch (ex : Exception) {
// handle the exception if you need to
}
// your codes here.
}
Warning: You'll lose access to the response when an exception occurred so you need to return an alternative response because it's required. And codes below try-catch statement won't be executed if there's no exception thrown by the chain.proceed() call.
I use retrofit2 and I'm learning RxJava (with Retrolambda). I'm trying to achieve following flow:
get list of user
for each user, get user detail info for given user_id.
return list of user with detail.
This is my code so far:
getUsers().flatMapIterable(users -> users)
flatMap(user -> getDetailInfo(user.getID()
.doOnNext(detailInfo -> user.setDetailInfo(detailInfo))
.map(detailInfo -> user))
.toList().subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
subscribe(users -> {}, error -> {});
The problem is when getDetailInfo gave 404 response, the observable enter to error scope even getUsers gave 200 response. How do I get the response enter to user scope as long as getUsers gave 200 response?
Hope I been enough clear.
Thanks
If you want to avoid your 404 to destroy your stream you should use onErrorResumeNext to convert your error into a default response like null and then you stream will survive even when the chained requests return error.