In this blog post, we will get familiar with terms like Disposable, DisposableObserver, and CompoundDisposable and will look into the basic steps to integrate RxJava2 in Android.
In our mobile world, we, the developers, often make API calls to the server in order to fetch the response and once received we update the User Interface. Now, think of a scenario where the API call is in progress and user has moved to another view or screen. What will happen when the response will be received and the observer will try to update the screen?
Yes, correct, the App might crash or might lead to a memory leak or screen freeze. This is where Disposable come to our rescue. We will look into the implementation part of Disposable a bit later.
Let’s look into how we can integrate RxJava2 and RxAndroid into our Project.
- Step 1: Integrating the libraries in App build.gradle
implementation "io.reactivex.rxjava2:rxjava:2.2.8" implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
- Step 2: Using the code in an Activity(Commit-1)
private static final String TAG = "RxSample"; private static final String SAY_HELLO = "Hello From Sarab"; private Observable<String> myObservable; private Observer<String> myObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myObservable = Observable.just(SAY_HELLO); myObservable.subscribeOn(AndroidSchedulers.mainThread()); myObserver = new Observer<String>() { @Override public void onSubscribe(Disposable d) { Log.d(TAG, "On Subscribe"); } @Override public void onNext(String s) { Log.d(TAG, "On Next"); Toast t = Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG); t.setGravity(Gravity.CENTER, 0, 0); t.show(); } @Override public void onError(Throwable e) { Log.d(TAG, "On Error"); } @Override public void onComplete() { Log.d(TAG, "On Complete"); } }; myObservable.subscribe(myObserver); } }
So, what just happened? If you check your logcat and the screen on your phone/ Emulator where you ran the sample application you will find following logs and a toast notification “Hello from Sarab“. The three methods, onSubscribe, OnNext and onComplete are called one after another, as discussed in our last post, as per their lifecycle methods.
31701-31701/blog.sarabjit D/RxSample: On Subscribe 31701-31701/blog.sarabjit D/RxSample: On Next 31701-31701/blog.sarabjit D/RxSample: On Complete
Bingo! You just created your first RxJava Sample App. Now, let’s go through the code and try to relate it to our first BlogPost.
So, in this sample app, we created an Observable and Observer Objects of type String. We have made use of the Just operator. The Just operator converts an item into an Observable that emits that item i.e whatever it receives as an input same is emitted as an output. If you pass null to Just, it will emit null as n output.
If we you look carefully, we have also used Scheduler here AndroidSchedulers.mainThread(), which helps us to show Toast Notification on the main thread.
Disposable
Let’s talk about disposable and the use case which we talked in the starting of this blog post. Firstly let’s look into the following picture:
The subscribe method of Observable returns us the Disposable object. Let’s modify our code accordingly(Commit-2).
Let’s Modify our Code and it look like this:
public class MainActivity extends AppCompatActivity { private static final String TAG = "RxSample"; private static final String SAY_HELLO = "Hello From Sarab"; private Observable<String> myObservable; private Observer<String> myObserver; private Disposable mDisposable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myObservable = Observable.just(SAY_HELLO); myObservable.subscribeOn(AndroidSchedulers.mainThread()); myObserver = new Observer<String>() { @Override public void onSubscribe(Disposable d) { mDisposable = d; Log.d(TAG, "On Subscribe"); } @Override public void onNext(String s) { Log.d(TAG, "On Next"); Toast t = Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG); t.setGravity(Gravity.CENTER, 0, 0); t.show(); } @Override public void onError(Throwable e) { Log.d(TAG, "On Error"); } @Override public void onComplete() { Log.d(TAG, "On Complete"); } }; myObservable.subscribe(myObserver); } @Override protected void onDestroy() { super.onDestroy(); mDisposable.dispose(); } }
In the above code, we have taken the disposable Object which we receive in the parameter of onSubscribe() and assigned it to Disposable object. This Disposable Object( mDisposable ) needs to be disposed of off once the user has finished interacting with the screen so that there is no memory leak or screen freeze or a crash as discussed earlier in the blog post.
Let’s modify above code(Commit-3), you will notice that instead of normal Observer( in Commit-2), we have taken DisposableObserver and used DisposableObserver object to call the dispose method in the onDestroy method of Activity or fragment. Yes, you noticed it correctly, now we have only three methods in our on Observer rather than four because now we do not need an onSubscribe() which used to return Disposable Object in its parameter.
public class MainActivity extends AppCompatActivity { private static final String TAG = "RxSample"; private static final String SAY_HELLO = "Hello From Sarab"; private Observable<String> myObservable; private DisposableObserver<String> mDisposableObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myObservable = Observable.just(SAY_HELLO); myObservable.subscribeOn(AndroidSchedulers.mainThread()); mDisposableObserver = new DisposableObserver<String>() { @Override public void onNext(String s) { Log.d(TAG, "OnNext"); Toast t = Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG); t.setGravity(Gravity.CENTER, 0, 0); t.show(); } @Override public void onError(Throwable e) { Log.d(TAG, "OnError"); } @Override public void onComplete() { Log.d(TAG, "OnComplete"); } }; myObservable.subscribe(mDisposableObserver); } @Override protected void onDestroy() { super.onDestroy(); mDisposableObserver.dispose(); } }
Composite Disposable
In a real-world scenario, we often call more than one API call in an Activity or Fragment. In such cases, we will have multiple Observer and for each Observer, we will require to call dispose method. If we forget to call this method for any of the Observer, it might lead to unexpected results. This is where Composite Disposable come to our rescue. We just need to add DisposableObserver object to Composite Disposable object and in onDestroy(), call the clear() of Composite Disposable object.
Let’s have a look at the code(Commit-4):
private static final String TAG = "RxSample"; private static final String SAY_HELLO = "Hello From Sarab"; private Observable<String> myObservable; private DisposableObserver<String> mDisposableObserver; private DisposableObserver<String> mDisposableObserver2; private CompositeDisposable mCompositeDisposable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCompositeDisposable=new CompositeDisposable(); myObservable = Observable.just(SAY_HELLO); myObservable.subscribeOn(AndroidSchedulers.mainThread()); mDisposableObserver = new DisposableObserver<String>() { @Override public void onNext(String s) { Log.d(TAG, "OnNext"); } @Override public void onError(Throwable e) { Log.d(TAG, "OnError"); } @Override public void onComplete() { Log.d(TAG, "OnComplete"); } }; mCompositeDisposable.add(mDisposableObserver); myObservable.subscribe(mDisposableObserver); mDisposableObserver2 = new DisposableObserver<String>() { @Override public void onNext(String s) { Log.d(TAG, "OnNext-Observer-2"); } @Override public void onError(Throwable e) { Log.d(TAG, "OnError-Observer-2"); } @Override public void onComplete() { Log.d(TAG, "OnComplete-Observer-2"); } }; mCompositeDisposable.add(mDisposableObserver2); myObservable.subscribe(mDisposableObserver2); } @Override protected void onDestroy() { super.onDestroy(); mCompositeDisposable.clear(); } }
Sometimes, developers often get confused, whether to use Composite Disposable clear() or Disposable dispose(). So what is the basic difference between these two?
- Dispose(): When we call this method, we will no longer be able to add the Disposable objects in the list i.e suppose you had two calls in a fragment/activity and you called dispose() after the first call, then you will require a different object of Compound Disposable to dispose of the Disposable Object of the second Observer for the corresponding call.
- Clear(): It clears the current list and you can keep adding the objects to clear them as per the need.
You can find Step- by -Step practical implementation from following Link:
https://github.com/Sarabjit-Blog/RxSample
Let me know if you face any issues or have any queries, until next chapter in the series, stay tuned…