Compare libraries for asynchronous queries

If you need to upload pictures and / or send http-requests in the project, perform any other long operation that might block the UI stream, then anyway you have to use the solution to perform asynchronous requests.

From the very beginning, in the old fashioned way, I will talk about standard AsyncTask / Loaders methods and explain why it is better not to use them. Then I will tell you about advanced methods for solving this problem.

image

The most trivial AsyncTask solution


Pros:
1. Easy to understand.
2. Solution out of the box.

Cons:
1. Memory leak when flipping the screen - the old activity is not destroyed until the task is completed, and the result comes in the old activity, and most likely you will catch exception.
2. No error handling.
3. Long operations will be interrupted as soon as the system decides to destroy your application (if you minimized it for example).

Code example:

requestDataTask = new AsyncTask() {
            @Override
            protected JSONObject doInBackground(Void... params) {
                //Для обработки ошибок обычно заводят поля Exception. (не лучшее решение)
                final String requestResult = apiService.getData();
                final JSONObject json = JsonUtils.parse(requestResult);
                lruCache.cacheJson(json);
                return json;
            }
        };


More modern solution - Loaders


The same as AsyncTask, except for one thing: when you flip the screen, you can get the result in a new activity. But the 2nd and 3rd problems are still present. Although Google recommends using loaders, I do not recommend doing this. You will have to write a lot of boilerplate code.

You can see an example here , or you can just believe me and not use Loaders. I don’t copy the code here, as these loaders are very verbose.

And now the best solution in my opinion - Robospice


Pros:
1. Robospice performs all operations in service. This means that if activity is destroyed, the task will continue to be executed anyway. The best solution for long tasks.
2. There are methods for handling errors.
3. Caching requests, integration with Retrofit .

But not everything is so rosy ... There are also disadvantages:
1. There is no method for checking whether the task is being performed or not, and this is a very important thing for me. There is a request pool on github with a solution to this problem - # 383 . Whoever needs it, use this fork.
2. Not the most convenient api in the world, but it will do.

Code example:

        spiceManager.execute(new SpiceRequest(String.class) {
                                 @Override
                                 public String loadDataFromNetwork() throws Exception {
                                     Thread.sleep(1000);// поддерживается обработка ошибок
                                     return "It works!!!!";
                                 }
                             }, "key", DurationInMillis.ALWAYS_RETURNED,
                new RequestListener() {
                    @Override
                    public void onRequestFailure(SpiceException spiceException) {
                    }
                    @Override
                    public void onRequestSuccess(String s) {
                    }
                });   


Noteworthy solution - RxJava


A good solution with a bunch of different features, you can read more on Habr in the publication "Reactive programming for Android . "
In short from me: there is error handling, support for the activity / fragment life cycle. But it is not suitable for long operations (unlike Robospice), plus it was personally difficult for me personally to deal with it, and still it seems that I do not understand the whole idea.

My own bike - Slige Task


Pros:
1. Easy to understand since based on AsyncTask.
2. There is error handling.
3. Support lifecycle activity.
4. Api is a little more comfortable.
5. It is easy to check whether a task is being executed or not.

Cons:
1. Scanty functionality, unlike RxJava.
2. Not suitable for long tasks (see Robospice).

Code example:

new SligeTask((notifier, strings) -> {
            try {
                Thread.sleep(1000);
                return "executed successfully!!!";
            } catch (InterruptedException e) {
                notifier.publishError(e); //сообщит об ошибке в ErrorListener
                return null;
            }
        },LOADER_ID)
                .setPreExecuteListener(() -> setLoading(true))
                .setResultListener(this)
                .setErrorListener(this)
                .setCancelListener(this)
                .setDefaultCallbackLimiter(this) //Предотвратит выполнение коллбеков, если activity умрёт
                .execute();


Conclusion


In conclusion, I would like to summarize. Personally, I will use the Robospice and SligeTask fork in my projects if the tasks are not long and do not require caching. You are free to choose whatever you want.

Yes, libraries are considered, of course, not all (there are a lot of them). I reviewed the most popular solutions. Here you can find a bunch of others.

Write in the comments which libraries you use and why.

If someone noticed lambdas in the code examples, but does not know what it is, how, and why, pay attention to this project .

Also popular now: