RxJava + Fast Android Networking

Big news: Fast Android Networking now supports RxJava.

Let’s explore why RxJava support is important.

What is RxJava?

RxJava is used for reactive programming. In reactive programming, the consumer reacts to the data as it comes in. Reactive programming allows for event changes to propagate to registered observers.

The main components: observables, observers, and subscriptions

RxJava provides Observables and Observers. Observables can send out values. Observers watch Observables by subscribing to them.

Observers are notified when an Observable emits a value and when the Observable says an error has occurred. They are also notified when the Observable sends the information confirming that it no longer has any values to emit.

The corresponding functions are onNext, onError, and onCompleted() from the Observer interface. An instance of Subscription represents the connection between an observer and an observable. We can call unsubscribe() on this instance to remove the connection.

Let’s understand this better by exploring an example:

Observable<String> observable = Observable.just("Cricket", "Football");

This is an Observable which emits strings and it can be observed by an Observer.

Let’s create an Observer:

Observer<String> observer = new Observer<String>() {
    @Override
public void onCompleted() {

    }

    @Override
public void onError(Throwable e) {

    }

    @Override
public void onNext(String response) {
        Log.d(TAG, "response : " + response);
    }
};

Now, we have to connect both Observable and Observer with a subscription. Only then can it actually do anything:

observable.subscribe(observer);

This will cause the following output, one line at a time:

Cricket
Football

This means the Observable emits two strings, one by one, which are observed by Observer.

Using RxJava with Fast Android Networking

If you aren’t yet familiar with Fast Android Networking, you can learn more about it here.

By using RxJava with Fast Android Networking, you can do many things like:

  1. Chaining requests
  2. Combining many requests and getting the combined response
  3. Cancelling the Network call when an activity is destroyed
  4. Using operators to filter out the response from Network, which you can then show to users
  5. Setting the thread on which we need a response from the server
  6. Proper Error handling

…and much more. Trust me, RxJava is an Art and endless possibilities await those who can master it. So let’s start mastering it by learning how to use it with the network layer.

To use RxJava in Fast Android Networking, you need to compile this.

compile 'com.amitshekhar.android:rx-android-networking:1.0.1'

If you are using RxJava2, then compile

compile 'com.amitshekhar.android:rx2-android-networking:1.0.1'

And Check here for RxJava2

Then initialize it in the onCreate() Method of the application class:

AndroidNetworking.initialize(getApplicationContext());

Make sure you have provided the internet permission in manifest.

Show me the code

I will try to give you a more friendly introduction to RxJava Operators, with plenty of complete code samples that you can actually compile and modify.

The below examples are based on RxJava one.

Example Using Map Operator

Use Case : Assume that we get ApiUser Object from server Api and our android client database accepts User Object. So after getting ApiUser from server, we are converting it into User Object using Map operator.

RxAndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAnUser/{userId}")
                .addPathParameter("userId", "1")
                .build()
                .getObjectObservable(ApiUser.class) // This returns you an Observable
                .subscribeOn(Schedulers.io()) // do the network call on another thread
                .observeOn(AndroidSchedulers.mainThread()) // return the result in mainThread
                .map(new Func1<ApiUser, User>() {
                    @Override
                    public User call(ApiUser apiUser) {
                        // here we get ApiUser from server
                        User user = convertApiUserToUser(apiUser);
                        // then by converting, we are returing user
                        return user;
                    }
                })
                .subscribe(new Observer<User>() {
                    @Override
                    public void onCompleted() {
                    // do anything onComplete    
                    }
                    @Override
                    public void onError(Throwable e) {
                    // handle error
                    }
                    @Override
                    public void onNext(User user) {
                    // do anything with user     
                    }
                });

Example Using Zip Operator : Combining two network requests

Use Case : Let say we get the list of football fans from one network call, and from another we get the list of cricket fans and then we have to find the user who loves both cricket and football. Here we are using Zip Operator to get the result of network call in one common method to apply our logic to find those who loves both.

/*
* This observable return the list of User who loves cricket
*/
private Observable<List<User>> getCricketFansObservable() {
    return RxAndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllCricketFans")
            .build()
            .getObjectListObservable(User.class);
}

/*
* This observable return the list of User who loves Football
*/
private Observable<List<User>> getFootballFansObservable() {
    return RxAndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllFootballFans")
            .build()
            .getObjectListObservable(User.class);
}

/*
* This do the complete magic, make both network call
* and then returns the list of user who loves both
* Using zip operator to get both response at a time
*/
private void findUsersWhoLovesBoth() {
    // here we are using zip operator to combine both request
    Observable.zip(getCricketFansObservable(), getFootballFansObservable(),
            new Func2<List<User>, List<User>, List<User>>() {
                @Override
                public List<User> call(List<User> cricketFans,
                                       List<User> footballFans) {
                    List<User> userWhoLovesBoth = 
                            filterUserWhoLovesBoth(cricketFans, footballFans);
                    return userWhoLovesBoth;
                }
            }
    ).subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<List<User>>() {
        @Override
        public void onCompleted() {
        // do anything onComplete
        }

        @Override
        public void onError(Throwable e) {
        // handle error
        }

        @Override
        public void onNext(List<User> users) {
        // do anything with user who loves both
        }
    });
}

private List<User> filterUserWhoLovesBoth(List<User> cricketFans, List<User> footballFans) {
    List<User> userWhoLovesBoth = new ArrayList<>();
    // your logic to filter who loves both
    return userWhoLovesBoth;
}

Example using flatMap and filter operator.

Use Case : Let say our server return the list of my friends , but we need to filter out only who those friends who is also following me. Here comes the filter operator to do so.

/*    
* First of all we are getting my friends list from
* server, then by using flatMap we are emitting users
* one by one and then after applying filter we are
* returning only those who are following me one by one.
*/

/*
* This observable return the list of User who are my friends
*/    
private Observable<List<User>> getAllMyFriendsObservable() {
   return RxAndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllFriends/{userId}")
           .addPathParameter("userId", "1")
           .build()
           .getObjectListObservable(User.class);
}

/*
* This method does all
*/       
public void flatMapAndFilter() {
   getAllMyFriendsObservable()
           .flatMap(new Func1<List<User>, Observable<User>>() { // flatMap - to return users one by one
               @Override
               public Observable<User> call(List<User> usersList) {
                   return Observable.from(usersList); // returning(emitting) user one by one from usersList.
               }
           })
           .filter(new Func1<User, Boolean>() { // filter operator
               @Override
               public Boolean call(User user) {
                   // filtering user who follows me.
                   return user.isFollowing;
               }
           })
           .subscribeOn(Schedulers.io())
           .observeOn(AndroidSchedulers.mainThread())
           .subscribe(new Observer<User>() {
               @Override
               public void onCompleted() {
                   // do anything onComplete
               }

               @Override
               public void onError(Throwable e) {
                   // handle error
               }

               @Override
               public void onNext(User user) {
                   // only the user who is following me comes here one by one
               }
           });
}

Another example using flatMap operator.

Use Case : Assume one api endpoint returns us the list of user and another returns the user detail corresponding to each user. Here we are using flatMap operator to do so.

/* Here first of all, we get the list of users from server.
* Then for each userId from user, it makes the network call to get the detail 
* of that user. 
* Finally, we get the userDetail for the corresponding user one by one
*/

/*
* This observable return the list of users.
*/
private Observable<List<User>> getUserListObservable() {
return RxAndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
        .addPathParameter("pageNumber", "0")
        .addQueryParameter("limit", "10")
        .build()
        .getObjectListObservable(User.class);
}

/*
* This observable return the userDetail corresponding to the user.
*/
private Observable<UserDetail> getUserDetailObservable(long userId) {
return RxAndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAnUserDetail/{userId}")
        .addPathParameter("userId", String.valueOf(userId))
        .build()
        .getObjectObservable(UserDetail.class);
}

/*
* This method do the magic - first gets the list of users
* from server.Then, for each user, it makes the network call to get the detail 
* of that user.
* Finally, we get the UserDetail for the corresponding user one by one
*/
public void flatMap() {
    getUserListObservable()
            .flatMap(new Func1<List<User>, Observable<User>>() { // flatMap - to return users one by one
                @Override
                public Observable<User> call(List<User> usersList) {
                    return Observable.from(usersList); // returning user one by one from usersList.
                }
            })
            .flatMap(new Func1<User, Observable<UserDetail>>() {
                @Override
                public Observable<UserDetail> call(User user) {
                    // here we get the user one by one
                    // and returns corresponding getUserDetailObservable
                    // for that userId
                    return getUserDetailObservable(user.id);
                }
            })
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<UserDetail>() {
                @Override
                public void onCompleted() {
                    // do something onCompleted
                }

                @Override
                public void onError(Throwable e) {
                    // handle error
                }

                @Override
                public void onNext(UserDetail userDetail) {
                    // here we get userDetail one by one for all users
                    Log.d(TAG, "userDetail id : " + userDetail.id);
                    Log.d(TAG, "userDetail firstname : " + userDetail.firstname);
                    Log.d(TAG, "userDetail lastname : " + userDetail.lastname);
                }
            });
}

There are plenty more examples here.

Thanks for reading this article.

Also, Let’s become friends on Twitter, Linkedin, Github, and Facebook.