Handling exceptions inside Observable.fromCallable() when subscription gets cleared - android

I have a situation where a long running process is wrapped in an Observable.fromCallable(). This process is an OkHttp call and, if terminated, will throw an IOException. If the observable is subscribed to, then the disposable is stored in a CompositeDisposable and the exception is handled as expected. However, my code will clear the CompositeDisposable in some cases, triggering the OkHttp thread termination with no error handling, causing the app to crash with an unhandled exception. Here's a simple unit test example of this problem:
#Test
public void test(){
CompositeDisposable compositeDisposable = new CompositeDisposable();
Observable<Object> o = Observable.fromCallable(new Callable<Object>() {
#Override
public Object call() throws Exception {
System.out.println("sleeping - this sleep will be interrupted when compositeDisposable gets cleared");
Thread.sleep(3000);
return null;
}
});
compositeDisposable.add(o.subscribeOn(new IoScheduler()).subscribe());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
compositeDisposable.clear();
}
Is there any way to work around this problem?

Unlike RxJava1, RxJava2 will not deliver this Exception to the Subscriber onError(), as you called cancel() to unsubscribe and don't wan't to get notifications anymore, so this kind of Exceptions which happens with the unsubscription code go by default now to Thread.currentThread().getUncaughtExceptionHandler().uncaughtException().
You can either wrap with try catch this kind of exceptions that may happens with cancel, or override the default behavior with:
RxJavaPlugins.setErrorHandler(Functions.<Throwable>emptyConsumer());
or any other handling you would like.
You should also read the full explanation by akarnokd at RxJava github.
Also refer to this discussion for the above mentioned solutions.

Related

Callable and future delay android main thread

I want to fetch some data from service by callable and future. This is one of my code:
#Override
public void getCIFilesType(Consumer<String> consumer) {
try {
consumer.accept(serviceExecutor.submit(() ->
service.getCi(EsupFactory.getConfigString(SETTING_ROOT_CI) + "GetCI",
translator.makeCiJsonObject("PCiName", "CI_FilesType")).execute())
.get().body().string());
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I have 10 method like this that execute like above.I used Executor service to run callable :
ExecutorService serviceExecutor = Executors.newSingleThreadExecutor();
I'm my activity I have a menu and then click on one item in the menu a fragment is a transaction in activity. All of the thread tasks immediately started in onViewCreated in fragment:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
presenter.getCis();
}
But when I clicked on the menu item UI is frizzed till all task down then transaction is down. This is not the first time that I have this problem. Every time I use callable and executor service I do not know why UI is frizzed!!!!
This is profiler :
Someone has some guidance for me!!? Please do not tell me to use asyncTask :-)
What is a read line?? In ui thread I just do transaction not execute long running task!!!
It happens because you're calling get() on the future returned by execute() method. According, to the docs,
If you would like to immediately block waiting for a task, you can use constructions of the form result = exec.submit(aCallable).get();
So, even though you use a background thread, by calling get you block your main thread until the background thread finishes your task.
To avoid UI junks you should've used callbacks.

Runtime error handling on android

I want to make some classes that catch runtime errors on android and offers the user the option to restore the last saved instance state of the app.
I was thinking of extending the Activity and Fragment classes and implement something that saves their state. In the meantime, another class handles every start of an activity or fragment, putting them in a stack.
I want to catch every possible exception in the app, hopefully making errors less bothersome for the user.
Any advice on how I should handle this?
How would this error checking influence the performance of an app?
It's not a good solution and i don't know if it's useful for you, but you can caught exceptions in Application Class.
public class MyApplication extends Application
{
public void onCreate ()
{
// Setup handler for uncaught exceptions.
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException (Thread thread, Throwable e)
{
handleUncaughtException (thread, e);
}
});
}
public void handleUncaughtException (Thread thread, Throwable e)
{
e.printStackTrace();
// do what ever you want.
}
}
You can use try catch blocks to catch runtime errors. If you use try catch efficiently with throws your app won't crash in first place hence no need to maintain stack of activities. btw maintaining stacks of previous activity in neither memory efficient nor advisable.

RxJava async task in Android

I am trying to implement an asynchronous task using RxJava in Android.
I tried the following code and it didn't work. It executes on the UI thread. I am using the following version of RxAndroid 0.24.0.
try {
Observable.just(someMethodWhichThrowsException())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> onMergeComplete());
}
catch (IOException e) {
e.printStackTrace();
}
However, the following works asynchronously for me.
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
#Override
public void call(Subscriber<? super String> subscriber) {
try {
someMethodWhichThrowsException();
} catch (IOException e) {
e.printStackTrace();
}
subscriber.onCompleted();
}
});
observable.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe();
I am trying to understand the following:
What is the difference between them?
What is the best practice while creating async tasks?
What is the difference between them?
Observable.just(someMethodWhichThrowsException())
.subscribeOn(Schedulers.newThread())
This is equivalent to the following:
Object someResult = someMethodWhichThrowsException();
Observable.just(someResult)
.subscribeOn(Schedulers.newThread())
As you can see this makes the synchronous method call first, then passes it to Observable.just to become an Observable.
Observable.create(new Observable.OnSubscribe<String>() {
#Override
public void call(Subscriber<? super String> subscriber) {
...
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
This method, however, will run the code in the call block on subscription. You've told it you want to subscribe on a new thread (subscribeOn(Schedulers.newThread())), so the subscription happens on a new thread, and the code which gets run on subscription (the call block) gets run on that thread too. This is similar behaviour to calling Observable.defer.
What is the best practice while creating async tasks?
Well, that's up to you and your desired behaviour. Sometimes you want the async code to begin running immediately (in which case you may want to cache it using one of the operators for that purpose). I'd definitely consider using the Async Utils library for this.
Other times, you'll want it to run only on subscription (which is the behaviour in the examples here) - for example if there are side-effects, or if you don't care when it's run and just want to use the built-ins to get something off the UI thread. Dan Lew mentions that Observable.defer is very handy for taking old code and getting it off the UI thread, during a conversion to Rx.
Use Async.start() from RxJava Async Utils library. This will call the function you provide on another thread.
Example:
Observable<String> observable = Async.start(new Func0<String>() {
#Override
public String call() {
try {
return someMethodWhichThrowsException();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
As you note, checked exceptions must be wrapped into RuntimeExceptions.
See also https://github.com/ReactiveX/RxJava/wiki/Async-Operators#start

What is the use case for a Android Future?

For context, I am an Android developer who is familiar with using AsyncTask's but has recently started working on a project which is heavily using Future's. The Futures do not have a callback and require checks on isDone() to determine progress.
I am having trouble understanding what the purpose and use case of Future is in Android. AsyncTask's provide what seems like the same functionality but with in my opinion a better interface which has callbacks built in that enable the client to clearly determine when the async operation is complete without having to constantly check isDone().
What is the use and purpose of a Future in Android, and why would I use Future or FutureTask over an AsyncTask?
The Future is part of the Java API, whereas the AsyncTask is Android specific. In fact, if you take a look at the source code of AsyncTask, you will see that it actually uses a FutureTask for its implementation:
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
#Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
The AsyncTask is thus just a helper class for short threading jobs, which also handles some thread pooling. My guess is that the original writers of your project were familiar with Futures, but not with AsyncTask, or generally disliked AsyncTask.
Since I dislike the original AsyncTask implementation due to its Exception handling, I went on a search for a better alternative, and found RoboGuice's SafeAsyncTask. In this implementation, an onException(Exception) callback is available, but RuntimeExceptions get propagated to that callback as well.
I think a NullPointerException should make the app just crash, and I modified this SafeAsyncTask a little while back to do exactly this. The result can be found here.

How to unsubscribe from an Observable when using an Android library

In Why is my timer Observable never called?
#Miguel Lavigne says:
"Keep in mind that if you're using Observables from within a Fragment or an Activity you should always make sure you unsubscribe from your Observables to eliminate chances of memory leaks."
It is clear to me how it works as long as I am using an Observable in an Activity, Fragment or View. But what if I am using it where there is no context?
My situation: I am having an external library which holds an object model. Each object has a .save() function, which is called from the UI. In save, an API endpoint call is performed by an Observable asynchronously.
Example:
public Overlay save() {
Observable.create(new Observable.OnSubscribe<Overlay>() {
#Override public void call(Subscriber<? super Overlay> subscriber) {
try {
Overlay overlay= OverlayEndpoint.insertOverlay(this); // call the API endpoint here
subscriber.onNext(overlay);
subscriber.onCompleted();
} catch (IOException e) {
subscriber.onError(e);
}
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Overlay>() {
#Override public void call(Overlay overlay) {
// process the saved result [omitted for brevity]
}
}, new Action1<Throwable>() {
#Override public void call(Throwable throwable) {
// put the overlay into a local upload queue in case the endpoint is unreachable [omitted]
}
});
return this; // return the call immediately
}
The Observable is for one-time use within save and becomes obsolete thereafter. How can I make sure it does not persist?
Situation 1: Normal unsubscribe. Is there a way to unsubscribe right from within the call(), once processing is complete?
Situation 2: For whatever reason the Observable stays in memory. Could I use .timeout() to ensure the Observable is destroyed after enough time has passed?
Situation 1: Normal unsubscribe. Is there a way to unsubscribe right from within the call(), once processing is complete?
In your case, Observable will be in memory before Action1<Overlay> or new Action1<Throwable> is called. But after one of them is called, GC should be able to clean the Observable.
Situation 2: For whatever reason the Observable stays in memory. Could I use .timeout() to ensure the Observable is destroyed after enough time has passed?
In your case, Schedulers.newThread() will create a new Thread to run the Observable.OnSubscribe<Overlay>.call. So if this method has not returned yet, such as OverlayEndpoint.insertOverlay will run about 10 minutes, Observable can not be cleaned by GC because this thread is still using it. There is nothing we can do unless there is an approach to cancel OverlayEndpoint.insertOverlay.

Categories

Resources