RxJava and RxAndroid
Rx is a reactive extension. Reactive programming takes the best of Observer Pattern, Itertor Pattern, and Functional Programming. It focuses on asynchronous data streams and the propagation of changes through those streams. RxAndroid is library, with addition of few classes to RxJava, to make it more suitable for Android platform. Specifically, it makes the Android application's main thread (or any given looper), available as RxJava scheduler, which decides the thread for a particular piece of code to run on.
In reactive programming, data is modeled as streams, which are sequences of values that arrive over time. For example, a stream could be a sequence of button clicks, typing events, a series of sensor readings, variation in GPS signal or a set of network responses, events with change in device location, gyroscopy events, remote network events, device hardware events, sensors events etc. Streams can be combined and transformed using various operators to produce new streams of data, which can then be processed further or used to drive application behavior.
Few key terms to understand Rxjava (or its extension RxAndroid) are:
- Obervable: Emits stream.
- Observer or Subscriber: Consumes stream. Multiple Observers can subscribe to a single Observable.
- Operators: Modify, transform, and manipulate emissions from Obervable, before receivd by Observer.
- Schedulers: Perform operations of Observable on different threads.
Though, RxJava and RxAndroid can make it easier to write efficient, responsive, and scalable Android apps. However, they can also add complexity to code, so it's important to weigh the benefits against the costs when deciding whether to use these libraries in a project.
RxAndroid Example Code
User.java
public class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
UserService.java
public class UserService { public Observable> getUsers() { return Observable.fromCallable(() -> { List
users = new ArrayList<>(); users.add(new User("A")); users.add(new User("B")); users.add(new User("C")); return users; }).delay(2, TimeUnit.SECONDS); } }
MainActivity.java
This example uses a single TextView to display the name of the first user in the list, here getUsers() method in UserService returns an Observable. The MainActivity class uses the subscribe() method to subscribe to the Observable. When the Observable emits a list of users, the onNext() method is called, and the name of the first user in the list is displayed in the TextView. The onError() method is called if there is an error, and the onComplete() method is called when the Observable completes. The Disposable returned by subscribe() is stored in the disposable field, and is disposed of in the onDestroy() method of the activity to prevent any memory leaks.public class MainActivity extends AppCompatActivity { private TextView nameTextView; private Disposable disposable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); nameTextView = findViewById(R.id.nameTextView); UserService userService = new UserService(); disposable = userService.getUsers() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer>() { @Override public void onSubscribe(@NonNull Disposable d) { disposable = d; } @Override public void onNext(@NonNull List
users) { nameTextView.setText(users.get(0).getName()); } @Override public void onError(@NonNull Throwable e) { Toast.makeText(MainActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } @Override public void onComplete() { // Do nothing } }); } @Override protected void onDestroy() { super.onDestroy(); disposable.dispose(); } }