Android

Introduction of ReactiveX Programming (RxJava, RxAndroid) Part-1

Pinterest LinkedIn Tumblr

We’re going to learn the basics of RxJava and RxAndroid through the example. This tutorial will help beginners, who want to learn RxJava and RxAndroid?

RxJava is a JavaVM implementation of ReactiveX a library for composing asynchronous and event-based programs by using observable sequence. You can create an asynchronous data stream on any thread, transform the data, and consume it by an observer. Rxjava offers a wide range of operators which can use for the data stream.

RxAndroid is specific to the Android platform. Schedulers introduced in RxAndroid. RxAndroid plays a major role in supporting the multithreading concept. You can find a lot of schedulers in this library but Schedulers.io() and AndroidSchedulers.mainThread() are extensively used in Android programming.

  • Schedulers.io() is using to perform non CP-intensive operation like network class with the server, reading files/disc and database operations.
  • AndroidSchedulers.mainThread() provides access to Android Main and UI thread. For example, operations like udpating UI or user interection happens on this thread.
  • Schedulers.newThread() create a thread each time when task schedule.
  • Schedulers.computation() used to perform CPU-intensive operation for processing huge data or image bitmap etc.
  • Schedulers.single() will execute all the tasks in sequential order they are added. For example, Thread1, Thread2, Thread3 etc. You can use this when you need to perform task step by step in sequential order.
  • schedulers.immediate() executes the task immedially in synchronous was by blockig the main thread.
  • Schedulers.from() use to create a scheduler from an executor by limiting number of threads to be created. When thread pool will complete then tasks will be queued.

Observable and Observers

RxJava is all about two key components, Observable and Observer. Observables are the source that emits each item to the observable. Before listening to the data from the observable, we need to subscribe to the observers first.

Look at the demo, please

User search demo with RxJava and RxAndroid

Let’s jump on to some code examples to understand the concepts of reactive programming.

1- Open the Android Studio and create a new project.

2- Open the build.gradle.xml file and enable the data binding feature in your project. If you’re not familiar with DataBinding, click here to read about DataBinding.

buildFeatures {
        dataBinding true
    }

3- Add the below dependencies in the project build.gradle.xml file.

dependencies {

    // rxjava
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'

    implementation 'androidx.appcompat:appcompat:1.4.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

4- Open the Colors.xml file and add the below code if you want to follow the sample

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>

    <!-- App colors -->
    <color name="color_bg">#121212</color>
    <color name="color_tv">#00FFFF</color>
    <color name="color_dark_black">#1D1D1D</color>
</resources>

5- Go to res->values and open the strings.xml file and add the below code

<resources>
    <string name="app_name">RxJavaExample (Part-1)</string>

    <!-- App strings -->
    <string name="str_verified_user">Verified User</string>
    <string name="str_un_verified_user">Un Verified User</string>
    <string name="str_john">John</string>
    <string name="str_mark">Mark</string>
    <string name="tv_user_address">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque quis elementum nisi. Vivamus neque leo, eleifend ut tempus elementum, dictum eget massa</string>
</resources>

6- Create a new Java class called UserM.java with three properties name, address, and isVerified. Add the below code

package com.example.rxjavaexamplepartone;

public class UserM {
    private String name;
    private String address;

    public boolean isVerified() {
        return isVerified;
    }

    public void setVerified(boolean verified) {
        isVerified = verified;
    }

    private boolean isVerified;


    public UserM(String name, String address, boolean isVerified) {
        this.name = name;
        this.address = address;
        this.isVerified = isVerified;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

7- Right-click on the res->layout file and create a new layout resource file called adapter_user_listing.xml. Add the below code if you want to keep it as like example design.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="user"
            type="com.example.rxjavaexamplepartone.UserM" />

    </data>

    <androidx.cardview.widget.CardView
        android:id="@+id/cardListing"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="5dp"
        android:minHeight="140dp"
        app:cardBackgroundColor="@color/color_dark_black"
        app:cardCornerRadius="5dp"
        app:cardMaxElevation="5dp"
        app:cardUseCompatPadding="true">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp">

            <TextView
                android:id="@+id/tvUsername"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.name}"
                android:textColor="@color/color_tv"
                android:textSize="20sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/tvUserAddress"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.address}"
                android:textColor="@color/white"
                android:textSize="16sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tvUsername" />

            <TextView
                android:id="@+id/verifiedUserStatus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                android:textColor="@color/white"
                android:text='@{user.verified ? "Verified": "Unverified"}' />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</layout>

8- Create another new Java class called AdapterUserListing.java. Add the below code

package com.example.rxjavaexamplepartone;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;

import com.example.rxjavaexamplepartone.databinding.AdapterUserListingBinding;

import java.util.List;

public class AdapterUserListing extends RecyclerView.Adapter<AdapterUserListing.ListingMHolder> {
    private List<UserM> userMList;
    private Context _context;

    public AdapterUserListing(List<UserM> userMList) {
        this.userMList = userMList;
    }

    protected class ListingMHolder extends RecyclerView.ViewHolder {
        private AdapterUserListingBinding userListingBinding;

        public ListingMHolder(AdapterUserListingBinding userListingBinding) {
            super(userListingBinding.getRoot());
            this.userListingBinding = userListingBinding;
        }
    }

    @NonNull
    @Override
    public ListingMHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        _context = parent.getContext();
        AdapterUserListingBinding adapterListingBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.adapter_user_listing, parent, false);
        return new ListingMHolder(adapterListingBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull ListingMHolder holder, int position) {
        UserM listingM = userMList.get(position);
        holder.userListingBinding.setUser(listingM);
    }

    @Override
    public int getItemCount() {
        return userMList.size();
    }

}

9- Open the MainActivity.java file and add the below code. As you watched in the video, this example is just filtering the verified and unverified users from the list. This example, I did with two methods. In the code, I added comments for understanding the code, how it is working? If you have still problems understanding the concept of reactive programming, comment here.

package com.example.rxjavaexamplepartone;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.util.Log;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.example.rxjavaexamplepartone.databinding.ActivityMainBinding;

import java.nio.file.DirectoryStream;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Predicate;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {
    private final static String tag = "RxJava";
    private List<UserM> filteredUserList;
    private AdapterUserListing adapterUserListing;
    private ActivityMainBinding activityMainBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        initComponents();
        initRcv();
        withSimpleMethodOne(true);
    }


    /**
     * initialize the array list object
     * initialize the listing adapter
     * set the listener of radio group
     */
    private void initComponents() {
        filteredUserList = new ArrayList<>();
        adapterUserListing = new AdapterUserListing(filteredUserList);
        activityMainBinding.rdoUserGrp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                filterUserData(checkedId == R.id.rdoUserVerified);
            }
        });
    }

    /**
     * setup the liner layout manager and set the direction orientation vertical
     * set the layout manager to RecyclerView
     */
    private void initRcv() {
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
        activityMainBinding.rcvListing.setLayoutManager(linearLayoutManager);
        activityMainBinding.rcvListing.setAdapter(adapterUserListing);
    }

    /**
     * In this method, we initialize the task observer
     * @param isUserFilterable this param will use for filter the verified and unverified user
     */
    private void withSimpleMethodOne(boolean isUserFilterable) {
        Observable<UserM> userMObservable = Observable.fromIterable(prepareDummyData())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .filter(userM -> userM.isVerified() == isUserFilterable);
        Observer<UserM> task = new Observer<UserM>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                Log.d(tag, "On Subscribe");
            }

            @Override
            public void onNext(@NonNull UserM userM) {
                filteredUserList.add(userM);
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Log.d(tag, "On Error");
            }

            @Override
            public void onComplete() {
                adapterUserListing.notifyDataSetChanged();
            }
        };
        userMObservable.subscribe(task);
    }
    /**
     * In this method, we initialize the task observer
     * @param isUserFilterable this param will use for filter the verified and unverified user
     */
    private void withSimpleMethodTwo(boolean isUserFilterable) {
        Observable<UserM> userMObservable = Observable.fromIterable(prepareDummyData())
                .subscribeOn(Schedulers.io())
                .filter(userM -> userM.isVerified() == isUserFilterable);
        userMObservable.subscribe(new Observer<UserM>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull UserM userM) {
                filteredUserList.add(userM);
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {
                adapterUserListing.notifyDataSetChanged();
            }
        });
    }

    /**
     * 
     * @param isUserVerified this bool will change according to radio button selection from user input
     *  As I explained in the MainActivity.java description, you have two methods to filter the users by using reactive programming.
     *  Right now, one method is using and second method is commented, you can test it both                   
     */
    private void filterUserData(boolean isUserVerified) {
        filteredUserList.clear();
        withSimpleMethodOne(isUserVerified);
       // withSimpleMethodTwo(isUserVerified);
    }

    /**
     * create a list of dummy data for verified and unverified users
     * @return the list of both verified and unverified users
     */
    private List<UserM> prepareDummyData() {
        List<UserM> userMS = new ArrayList<>();
        String strJohn = getString(R.string.str_john);
        String strMark = getString(R.string.str_mark);
        String address = getString(R.string.tv_user_address);

        // for verified and un verified user
        for (int j = 0; j < 20; j++) {
            userMS.add(new UserM((j % 2 == 0 ? strJohn : strMark) + "_" + j, address, j % 2 == 0));
        }
        return userMS;
    }
}

Thanks for reading the tutorial. Subscribe to my YouTube channel. Like and Share my Facebook page with your friends.

Write A Comment