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
Related
I have a button in my MapsActivity that communicates to the Wear app. The following Thread is executed:
class NewThread extends Thread {
String path;
String message;
NewThread(String p, String m) {
path = p;
message = m;
}
public void run() {
Task<List<Node>> wearableList =
Wearable.getNodeClient(getApplicationContext()).getConnectedNodes();
try {
List<Node> nodes = Tasks.await(wearableList);
for (Node node : nodes) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(MapsActivity.this).sendMessage(node.getId(), path, message.getBytes());
try {
Integer result = Tasks.await(sendMessageTask);
sendmessage("I just sent the wearable a message " + sentMessageNumber++);
} catch (final ExecutionException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[1] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
} catch (final InterruptedException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[2] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
}
}
} catch (final ExecutionException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[3] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
} catch (final InterruptedException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[4] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
}
}
}
But I get the following error in the image when trying to accomplish the Thread.
This happens on an Emulator where the WearOS app/api is not available to me (Probably on real devices which do not have WearOS App/Api too).
It happens on the Wearable.getMessageClient(MapsActivity.this).sendMessage(node.getId(), path, message.getBytes());.
I didn't find a clean way of checking the Wear API to be available so I am trying to get the capabilities first, catching the ApiException and setting a isWearableAvailable property:
private fun checkCapability() {
try {
val capability = capabilityClient
.getCapability(CAPABILITY_XYZ, CapabilityClient.FILTER_REACHABLE)
.await()
isConnected = capability.nodes.any(Node::isNearby)
if (BuildConfig.DEBUG) Log.d(LOG_TAG,
"Capability: ${capability.nodes.joinToString()}} > ${isConnected}")
isWearableApiAvailable = true
} catch (e: ApiException) {
isWearableApiAvailable = false
}
}
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.
I would like to wrap a synchronous method from parse.com mainly ParseObject.save() into a RxJava wrapper. I have come up with the below:
public Observable<Void> uploadFix(final ParseObject parseObject) {
return Observable.defer(new Func0<Observable<Void>>() {
#Override
public Observable<Void> call() {
try {
return Observable.just(fix.save());
} catch (ParseException e) {
return Observable.error(e);
}
}
});
}
This is giving me an error: Observable cannot be applied to void.
Basically is there any way to wrap this call with RxJava and get notified if the save is successful?
fix.save() returns void so you can't use it as an argument to Observable.just(). You can return a boolean instead.
public Observable<Boolean> uploadFix(final ParseObject parseObject) {
return Observable.defer(new Func0<Observable<Boolean>>() {
#Override
public Observable<Boolean> call() {
try {
fix.save();
return Observable.just(true);
} catch (ParseException e) {
return Observable.error(e);
}
}
});
}
you could also use a Completable. It is used when you don't except a return-value. If RxJava for Android will bump-up to version 2, you can not use Observabl anymore, because null values are not allowed anymore.
Please look at my example. I am using RxJava2-RC5 for testing. Test should complete within 2 seconds + overhead.
#org.junit.Test
public void name() throws Exception {
Completable completable = Completable.fromAction(() -> doWorkSync());
TestObserver<Void> test = completable.test();
test.assertComplete();
}
private void doWorkSync() {
// simulate work
try {
Thread.sleep(2_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
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.
Can I do this:
try {
loadItem();
} catch (NullPointerException e) {
Toast.makeText(getActivity(),"Sorry, we couldn't load that item. Please try again",Toast.LENGTH_SHORT).show();
}
And catch any NullPointerExceptions that might occur in loadItem()?
Yes. Unless loadItem() itself catches the exception without rethrowing, it will bubble up to the caller.
You can test this out with the following program, which outputs Ouch! due to the exception handler kicking in:
public class DodgyProg {
public static void loadItem() {
throw new NullPointerException();
}
public static void main(String []args){
try {
loadItem();
} catch (NullPointerException e) {
System.out.println("Ouch!");
}
}
}