Replace Android AsyncTask with RxJava
Today is the day when we will say goodbye to AsyncTask. It will be replaced by our new friend RxJava which is quite in news now a days. We will be covering how RxJava will do the work of AsyncTask. This post is included in series of post which will cover RxJava in detail.
But why ?
That ok but why do we need to replace our AsyncTask? Because RxJava is more easier to use and we can add more features and controls without changing anything and by just plugging some functions in between. This will make our life easier and manageable. Also there will be much less code and no subclassing at all.
Lets start coding
First of all you have to add support for RxJava in your gradle file as explained in this tutorial. We are using lambda expression in this tutorial for code clarity, so you should setup that also from our tutorial.
Now we are ready to use RxJava with Lambda expression.
This code will sleep for 5 sec on worker thread(not on main thread) and then simply print the letter count of passed string. There will be a loader which will show rotating animation from start to end of this operation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
/** * Created by aman.yadav on 01/01/17. */ public class AsyncTaskDemoFragment extends BaseFragment { @BindView(R.id.progressBar) ProgressBar progressBar; @BindView(R.id.textView) TextView textView; @Override public int setLayout() { return R.layout.fragment_async_task; } @OnClick(R.id.button) void buttonClicked() { startAsyncTask("Hello"); } //-------------------Main logic here-------------------// private void startAsyncTask(String input) { Observable.just(input) .map(this::doInBackground) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnSubscribe(this::onPreExecute) .subscribe(this::onPostExecute); } //------------- full mapping to async task functions -----------------// //pre execute work here private void onPreExecute() { progressBar.setVisibility(View.VISIBLE); } //do background things here private int doInBackground(String data) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return data.length(); } //post execution work here private void onPostExecute(int result) { progressBar.setVisibility(View.GONE); textView.setText("Length of input is " + result); } } |
We will use RxJava.just() for emitting data. Here string is being emitted by just operator. This can be of any type you want, we have taken string for simplicity. It can be url that will be used to download data.
When we click on button then startAsyncTask is called which will emit string using just operator. Now this string is passed to map operator which basically converts one type to other. Here its converting String to int. Expanded code for this step is below.
1 2 3 4 5 6 |
map(new Func1<String, Integer>() { @Override public Integer call(String s) { return doInBackground(s); } }) |
So basically all the background processing will take place in this function which is equivalent to doInBackground() in AsyncTask.
Next comes in subscribeOn(Schedulers.io()) which tells RxJava to do this processing on separate worker thread. So basically you can do anything on separate thread just by add a single function.
observeOn(AndroidSchedulers.mainThread()) is where the beauty of RxJava is fully visible. This tells Rxjava to do final result delivery on Android main thread. So when data is delivered after processing then it will be delivered on main thread.
RxJava uses subscription model where a subscriber subscribe for result. doOnSubscribe(this::onPreExecute) calls onPreExecute() function when subscriber subscribe for data. Simple code without lambdas looks like this.
1 2 3 4 5 6 |
doOnSubscribe(new Action0() { @Override public void call() { onPreExecute(); } }) |
Finally subscribe to get result. subscribe(this::onPostExecute) In expanded form it looks like this. This will call onPostExecute with result after the background work is done.
1 2 3 4 5 6 |
subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { onPostExecute(integer); } }) |
Thats all we need to do right now. Please comment for queries.