The Log.d(...) expression in the catch(...) block below gets executed (I can see the log output in Android Studio), but the debugger won't stop at the breakpoint set at that very same line. Why is that? The debugger stops at other breakpoints.
Observable.create(new Observable.OnSubscribe<MobileBankIdSessionResponse.MobileBankIdSession>() {
#Override
public void call(final Subscriber<? super MobileBankIdSessionResponse.MobileBankIdSession> subscriber) {
Schedulers.newThread().createWorker().schedule(new Action0() {
#Override
public void call() {
try {
MobileBankIdSessionResponse r = User.getMobileBankIdSession(reference, nationalIdentity).toBlocking().first();
String progressCode = r.getResponse().progress.progressCode;
if (StringUtils.equals(progressCode, "COMPLETE")) {
subscriber.onNext(r.getResponse());
subscriber.onCompleted();
} else if (StringUtils.equals(progressCode, "USER_SIGN")
|| StringUtils.equals(progressCode, "OUTSTANDING_TRANSACTION")) {
Schedulers.newThread().createWorker().schedule(this, 2, TimeUnit.SECONDS);
} else if (StringUtils.equals(progressCode, "NO_CLIENT")) {
subscriber.onError(new Throwable("Fel vid signering"));
}
} catch (Exception e) {
Log.d("AtError", "here");
subscriber.onError(e);
}
}
});
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<MobileBankIdSessionResponse.MobileBankIdSession>() {
#Override
public void onCompleted() {}
#Override
public void onError(Throwable throwable) {
mUserLoggedInOutSubject.onNext(Pair.create(throwable.getMessage(), LoginStates.ERROR));
}
#Override
public void onNext(MobileBankIdSessionResponse.MobileBankIdSession mobileBankIdSession) {
setSession(mobileBankIdSession.session, nationalIdentity);
}
});
To anyone who came here for answer, It is possible you have not called .subscribe(e ->{}); on the Single ,Flowable etc Object you are using.
Related
I am fetching response from server using 3 web API calls, but in case of getting IOException i have to retry those calls for 3 times using retryWhen().
How can I achieve that?
i have tried adding below code, but not getting expected output
retryWhen(new Function<io.reactivex.Observable<Throwable>, ObservableSource<?>>() {
int retryCount = 0;
#Override
public ObservableSource<?> apply(io.reactivex.Observable<Throwable> errors) throws Exception {
return errors.flatMap(new Function<Throwable, ObservableSource<?>>() {
#Override
public ObservableSource<?> apply(Throwable throwable) throws Exception {
retryCount++;
if (retryCount < 4) {
Log.e(TAG, " Exception retrying = "+retryCount );
return io.reactivex.Observable.just("");
}
return io.reactivex.Observable.error(throwable);
}
});
}
})
public void onClickLogin(View view) {
io.reactivex.Observable
.zip(getLogin(Constants.EMAILID, Constants.PASSWORD),
getUserInfo(Constants.EMAILID, Constants.PASSWORD),
getProductDetails(Constants.EMAILID, Constants.PASSWORD).subscribeOn(Schedulers.io()),
.observeOn(AndroidSchedulers.mainThread())
new Function3<List<LoginModule>,
List<UserInfoModule>, ProductModule, AllZipData>() {
#Override
public AllZipData apply(List<LoginModule> loginModuleList, List<UserInfoModule> useerInfoModules, ProductModule productModule) throws Exception {
AllZipData allZipData = new AllZipData();
allZipData.setLoginModuleList(loginModuleList);
allZipData.setUserInfoModuleList(UserInfoModule);
allZipData.setProductModule(productModule);
return allZipData;
}
}).subscribe(new Observer<AllZipData>() {
#Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
#Override
public void onNext(AllZipData allZipData) {
MyDatabase MyDatabase = MyDatabase.getInstance(context);
for (int i = 0; i < allZipData.getUserInfoModuleList().size(); i++) {
UserInfoTable userInfoTable = new UserInfoTable();
userInfoTable.setValue1(allZipData.getUserInfoModuleList().get(i).getValue1());
userDatabase.userDao().insertUserInfo(userInfoTable);
}
}
#Override
public void onError(Throwable e) {
Log.e(TAG, "onError: all zip data " + e.toString());
}
#Override
public void onComplete() {
Log.e(TAG, "onComplete: all data zipped");
}
});
}
There's a version of retry that calls a predicate to determine if the stream should be subscribed or not - if you should retry. The predicate receives 2 arguments - number of attempts and the throwable. It seems to be what you want. I'd try:
observableThatMightError
.retry((count, throwable) -> throwable instanceof IOExceptio && count <= 3)
this will retry if the throwable is an IOException and you haven't retried yet for at least 3 times.
I have following code
private void tryToLauch() {
try {
launch();
} catch (MyException e) {
postError(e.getErrorMessage());
e.printStackTrace();
}
}
How can I convert it to Rx that will retry in some period in case of exception ?
Given that your method have as return type void, I suggest you to use a Completable.
You can try this solution, using RxJava 2
Completable myCompletable = Completable.fromAction(new Action() {
#Override
public void run() throws Exception {
launch();
}
}).retry(3 /*number of times to retry*/, new Predicate<Throwable>() {
#Override
public boolean test(Throwable throwable) throws Exception {
return throwable instanceof MyException;
}
});
Then subscribe to the Completable
myCompletable.subscribeOn(SubscribeScheduler)
.observeOn(ObserveScheduler)
.subscribe(this::onComplete, this::onError);
Hope this helps.
mSubscription = RxSearchView.queryTextChangeEvents(mSearchView)
.subscribeOn(AndroidSchedulers.mainThread())
.debounce(600, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.filter(new Func1<SearchViewQueryTextEvent, Boolean>() {
#Override
public Boolean call(SearchViewQueryTextEvent searchViewQueryTextEvent) {
String query = searchViewQueryTextEvent.queryText().toString();
if (!TextUtils.isEmpty(query) && query.length() >= 11) {
if (!CommonUtil.isMobileNumber(query)) {
PromptManager.getInstance().showToast("please input valid phone");
return false;
}
}
boolean b = !TextUtils.isEmpty(searchViewQueryTextEvent.queryText().toString());
return b;
}
})
.switchMap(new Func1<SearchViewQueryTextEvent, Observable<BaseResponseWrapper<SearchUserResponse>>>() {
#Override
public Observable<BaseResponseWrapper<SearchUserResponse>> call(SearchViewQueryTextEvent searchViewQueryTextEvent) {
// Why run in the main thread here
// 2016/6/12 reset api request
String res = searchViewQueryTextEvent.queryText().toString();
return RetrofitManager.newInstance().getApi().searchUserByPhone(res);
}
})
// switch io thread
.subscribeOn(Schedulers.io())
.map(new Func1<BaseResponseWrapper<SearchUserResponse>, List<SearchUserResponse>>() {
#Override
public List<SearchUserResponse> call(BaseResponseWrapper<SearchUserResponse> fuzzyUserRes) {
// some code here
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<SearchUserResponse>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
LogUtils.w("end thread:" + Thread.currentThread().getName());
LogUtils.w("e :" + e);
**//there throw exception android.os.NetworkOnMainThreadException**
}
#Override
public void onNext(List<SearchUserResponse> fuzzyUsers) {
updateUI(fuzzyUsers);
}
});
When I input to the searchview , onError method will throw android.os.NetworkOnMainThreadException.
I have been in the
After switchmap switch to the IO thread.
I use rxjava version :
'io.reactivex:rxjava:1.1.5'.
what can I do?
You can't call subscribeOn twice in the same stream. Only the first will count.
Your code should look like this:
mSubscription = RxSearchView.queryTextChangeEvents(mSearchView)
.debounce(600, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.filter(new Func1<SearchViewQueryTextEvent, Boolean>() {
#Override
public Boolean call(SearchViewQueryTextEvent searchViewQueryTextEvent) {
String query = searchViewQueryTextEvent.queryText().toString();
if (!TextUtils.isEmpty(query) && query.length() >= 11) {
if (!CommonUtil.isMobileNumber(query)) {
PromptManager.getInstance().showToast("please input valid phone");
return false;
}
}
boolean b = !TextUtils.isEmpty(searchViewQueryTextEvent.queryText().toString());
return b;
}
})
// switch io thread
.observeOn(Schedulers.io())
.switchMap(new Func1<SearchViewQueryTextEvent, Observable<BaseResponseWrapper<SearchUserResponse>>>() {
#Override
public Observable<BaseResponseWrapper<SearchUserResponse>> call(SearchViewQueryTextEvent searchViewQueryTextEvent) {
// Why run in the main thread here
// 2016/6/12 reset api request
String res = searchViewQueryTextEvent.queryText().toString();
return RetrofitManager.newInstance().getApi().searchUserByPhone(res);
}
})
.map(new Func1<BaseResponseWrapper<SearchUserResponse>, List<SearchUserResponse>>() {
#Override
public List<SearchUserResponse> call(BaseResponseWrapper<SearchUserResponse> fuzzyUserRes) {
// some code here
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<SearchUserResponse>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
LogUtils.w("end thread:" + Thread.currentThread().getName());
LogUtils.w("e :" + e);
**//there throw exception android.os.NetworkOnMainThreadException**
}
#Override
public void onNext(List<SearchUserResponse> fuzzyUsers) {
updateUI(fuzzyUsers);
}
});
As long as observeOn is a downstream operator, you should use them to switch over threads many times.
Hope that it helps.
I want to use RxAndroid in my project,
and i make the thread sleep for 50ms
but it caused anr,the code
public void getTypeAndCommodity() {
Observable.from(getCommodities())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Commodity>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Commodity commodity) {
}
});
}
and the getCommodities:
private ArrayList<Commodity> getCommodities() {
// some test info
ArrayList<Commodity> list = new ArrayList<>();
for (int i = 0; i < 99; i++) {
Commodity commodity = new Commodity();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
commodity.setName("name" + i);
commodity.setType("type" + (i + 1) / 10);
list.add(commodity);
}
return list;
}
why it cause anr?please help
This happens because getCommodities() is executed in main thread, and only the item emited is executed in io thread with subscribeOn(Schedulers.io()). If you want to execute getCommidities() in background thread too, you need to create an observable with defer() method:
Observable.defer(new Func0<Observable<Object>>() {
#Override public Observable<Object> call() {
return Observable.from(getCommodities());
}
}).subscribeOn(Schedulers.io())...
If you need more info: http://blog.danlew.net/2015/07/23/deferring-observable-code-until-subscription-in-rxjava/
I'm trying to suppress an error with RX plugin, but the app is still crashing. Am I doing anything wrong or plugin error handler is just for reporting and cannot prevent the crash?
public void testClick(View view) {
RxJavaPlugins.getInstance().registerErrorHandler(new RxJavaErrorHandler() {
#Override
public void handleError(Throwable e) {
e.printStackTrace();
}
});
final PublishSubject<Integer> hot = PublishSubject.create();
hot
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {
#Override
public void call(Integer value) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("Result");
}
});
Observable.range(0, 100).subscribe(hot);
}
If you look at _onError method in SafeSubscriber class you'll find :
try {
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
} catch (Throwable pluginException) {
handlePluginException(pluginException);
}
try {
actual.onError(e);
} catch {
...
}
You can see that RxJavaPlugins ErrorHandler doesn't affect further error processing and it should be used to log/report errors