RxBinding with RxJava in android

In my last tutorials, I have marked about how RxJava is working with the RxAndroid world. We understood what is Rx does? In the Rx world, it means Reactive Extension it means when anything changes it will react something. It is strongly follows the observer pattern. If you want to check What is Observable and How Observer gets notify once you anything changes in Observable Object. I would strongly recommend please check this links RxJava in Android part1 and RxJava in Android part2.
Now In RxWorld, the new terminology comes RxBinding. What is RxBinding? It is mapping an Observable to Android events (view, click) very strongly. I have marked that in the old pattern we have used many callback and listener. It is very difficult to understand for any new developer and it does not give any proper Architecture of our project. It makes always confusion to the developer to maintain the callback. It really makes our life hell. 

RxBinding will give the best Rx Architecture and makes your code structure quite good. I believe that RxBinding will provide the most efficient way of mapping listeners to Observables. It is working quite good with any design pattern. 

Let's check How we can use RxBinding with EditText for text change listener. 

   private void setupRxListener() {
        RxTextView.textChanges(emailEditText).subscribe(new Consumer() {
            @Override
            public void accept(@NonNull CharSequence charSequence) throws Exception {
                Toast.makeText(RxBindTestActivity.this, charSequence, Toast.LENGTH_LONG).show();
            }
        });
    }

Great That is very simple. For the best practice, You need to bind the view or layout by using ButterKnief and unBind it on onDestroy() method. It avoid the memory leak. Some time resources are taking a lot of memory. In this case, it gives OutOfMemory and it gives backpressure on the user interface. To avoid this RxJava version1 rewritten and came new concept of Flowable which handle the backpressure.

Flowable is the just updated version of Observable. What Observable does same and everything is done by Flowable. Only thing change in Flowable is that it can handle the backpressure on the user interface.

So the question is where we need to use Flowable. You can use Flowable if you need any long operation kind of thing for example reading or parsing files from disk, reading the database and any networking operation there we can use Flowable. It can handle the backpressure easily to maintain the buffer. For more detail, you can check the official documentation RxBinding.

Lets me give one example of the login page and used validation by using RxBinding by using RxJava and RxAndroid.

RxBindTestActivity.java

  
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Patterns;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.jakewharton.rxbinding2.widget.RxTextView;


import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.subscribers.DisposableSubscriber;

/**
 * Created by sunil on 19-03-2017.
 */

public class RxBindTestActivity extends AppCompatActivity {

    @BindView(R.id.email)
    EditText emailEditText;

    @BindView(R.id.password)
    EditText passwordEdiText;

    @BindView(R.id.login)
    Button login;

    Flowable emailFlowable;
    Flowable passFlowable;
    Unbinder unBinder;
    private boolean isValidForm;

    private DisposableSubscriber disposableSubscriber;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxbind);
        unBinder = ButterKnife.bind(this);

        initView();
        checkValidation();

    }

    @OnClick(R.id.login)
    public void loginClick() {
       if (isValidForm){
           Toast.makeText(RxBindTestActivity.this, "Login Completed", Toast.LENGTH_LONG).show();
       }else{
           Toast.makeText(RxBindTestActivity.this, "Something is not valid", Toast.LENGTH_LONG).show();
       }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (!disposableSubscriber.isDisposed()) {
            disposableSubscriber.dispose();
        }
        unBinder.unbind();
    }

    private void initView() {
        emailFlowable = RxTextView.textChanges(emailEditText).skip(1).toFlowable(BackpressureStrategy.LATEST);
        passFlowable = RxTextView.textChanges(passwordEdiText).skip(1).toFlowable(BackpressureStrategy.LATEST);
    }

    private void checkValidation() {

        disposableSubscriber = new DisposableSubscriber() {
            @Override
            public void onNext(Objecti object1) {
                if (object1 instanceof Boolean) {
                    boolean isValid = (boolean) object1;
                    if (isValid) {
                        // valid form
                        login.setAlpha(1);
                    } else {
                        // invalid form
                        login.setAlpha(0.3f);
                    }
                }

            }

            @Override
            public void onError(Throwable t) {
                Toast.makeText(RxBindTestActivity.this, "Error: " + t, Toast.LENGTH_LONG).show();
            }

            @Override
            public void onComplete() {
                Toast.makeText(RxBindTestActivity.this, "Good to go", Toast.LENGTH_LONG).show();
            }
        };

        Flowable.combineLatest(emailFlowable, passFlowable, new BiFunction(){

            @Override
            public Object apply(@NonNull CharSequence newEmail, @NonNull CharSequence newPassword) throws Exception {

                boolean emailValid = !TextUtils.isEmpty(newEmail) && Patterns.EMAIL_ADDRESS.matcher(newEmail).matches();
                if (!emailValid) {
                    emailEditText.setError("Invalid Email!");
                }

                boolean passValid = !TextUtils.isEmpty(newPassword) && newPassword.length() > 6;
                if (!passValid) {
                    passwordEdiText.setError("Invalid Password!");
                }
                isValidForm = emailValid && passValid;
                return isValidForm;
            }
        }).subscribe(disposableSubscriber);

    }
}

activity_rxbind.xml

  
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp">

   <EditText
        android:id="@+id/email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Email"/>

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:hint="Enter Password"
        android:layout_below="@+id/email"/>

    <Button
        android:layout_marginTop="20dp"
        android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Login"
        android:background="@color/colorPrimary"
        android:textColor="#fff"
        android:layout_below="@+id/password"/>

</RelativeLayout>


I think we can start using the Rx means Reactive. It provides us a lot more feature to make your code structure and powerful. Thanks for reading this post.

Comments

Popular posts from this blog

Service LifeCycle

NavigationView Drawer Expandable menu Item in ANdroid

Custom SeekBar (Discrete SeekBar) in android