This is the 8th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

Leisure time to write out some insights, the length is longer, this article is the last one, you can see my home page to get the PDF version of the file

Application scenarios and usage of RxJava

1. Integration with Retrofit

Retrofit is a well-known web request library for Square. Those of you who haven’t used Retrofit can skip this section

I mean, every scenario I’ve given you is just an example, and there’s no context between the examples, it’s just a primer, so you

You can skip this and watch another scene.

Retrofit provides the traditional Callback API as well as the RxJava version of the Observable API. The following I

By way of comparison, the RxJava version of Retrofit’s API differs from the traditional version.

Take the interface to get a User object as an example. Using Retrofit’s traditional API, you can define requests like this:


@GET("/user")

public void getUser(@Query("userId") String userId, Callback<User> callback);
Copy the code

During application construction, Retrofit automatically implements methods and generates code so that developers can use the following methods

Get a specific user and process the response:


getUser(userId, new Callback<User>() {

@Override

public void success(User user) {

userView.setUser(user);

}

@Override

public void failure(RetrofitError error) {

// Error handling. }};Copy the code

Using the RXJava-style API, the same request is defined like this:


@GET("/user")

public Observable<User> getUser(@Query("userId") String userId);
Copy the code

Here’s how it works:


getUser(userId)

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer<User>() {

@Override

public void onNext(User user) {

userView.setUser(user);

}

@Override

public void onCompleted() {

}

@Override

public void onError(Throwable error) {

// Error handling}});Copy the code

See the difference?

In RxJava form, Retrofit encapsulates the request into an Observable, which calls onNext() after the request, or after the request

OnError () is called on failure.

By contrast, the Callback form and Observable form look different, but they are similar in nature and detail

The Observable form seems to be worse than the Callback form. So why does Retrofit support RxJava?

Because it works! You can’t tell from this example because this is just the simplest case. And once the situation is complicated, Callback shape

The formula will soon start to be a headache. Such as:

Imagine a situation where the User fetched by your program should not be displayed directly, but should first be compared with data in the database

And correction after display. Callback: Callback Callback


getUser(userId, new Callback<User>() {

@Override

public void success(User user) {

processUser(user); // Try to correct User data

userView.setUser(user);

}

@Override

public void failure(RetrofitError error) {

// Error handling}};Copy the code

Any questions?

It’s easy, but don’t do it. Why is that? Because doing so can affect performance. Database operations are heavy and cost a read/write operation

10~20ms is common, and this time can easily lead to interface lag. So in general, avoid it if you can

Process the database in the main thread. So to improve performance, this code can be optimized:


getUser(userId, new Callback<User>() {

@Override

public void success(User user) {

new Thread() {

@Override

public void run() {

processUser(user); // Try to correct User data

runOnUiThread(new Runnable() { // Cut back to the UI thread

@Override

public void run(){ userView.setUser(user); }}); }).start(); } @Override publicvoid failure(RetrofitError error) {

// Error handling}};Copy the code

Performance issues resolved, but… This code is really too messy, the indented mystery ah! Messy code is often more than just an aesthetic problem because of the code

The more cluttered the project, the more difficult it is to read, and a project full of cluttered code will undoubtedly reduce the readability of the code, resulting in team development efficiency

Decrease and error rate increase.

At this point, if you use RxJava form, much easier to do. The code in RxJava form looks like this:


getUser(userId)

.doOnNext(new Action1<User>() {

@Override

public void call(User user) {

processUser(user);

})

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer<User>() {

@Override

public void onNext(User user) {

userView.setUser(user);

}

@Override

public void onCompleted() {

}

@Override

public void onError(Throwable error) {

// Error handling}});Copy the code

The background code and the foreground code are all in one chain, which is much clearer.

Another example: suppose the /user interface is not directly accessible, but needs to be filled in with a token obtained online. What does the code do

Write?

Callback method, which can be nested: @get ("/token")

public void getToken(Callback<String> callback);

@GET("/user")

public void getUser(@Query("token") String token, @Query("userId") String

userId, Callback<User> callback);

getToken(new Callback<String>() {

@Override

public void success(String token) {

getUser(token, userId, new Callback<User>() {

@Override

public void success(User user) {

userView.setUser(user);

}

@Override

public void failure(RetrofitError error) {

// Error handling}}; } @Override publicvoid failure(RetrofitError error) {

// Error handling}});Copy the code

There’s no performance problem, but you know it, I know it, you know it better if you’re working on a big project.

With RxJava, the code looks like this:


@GET("/token")

public Observable<String> getToken();

@GET("/user")

public Observable<User> getUser(@Query("token") String token, @Query("userId")

String userId);

getToken()

.flatMap(new Func1<String, Observable<User>>() {

@Override

public Observable<User> onNext(String token) {

return getUser(token, userId);

})

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer<User>() {

@Override

public void onNext(User user) {

userView.setUser(user);

}

@Override

public void onCompleted() {

}

@Override

public void onError(Throwable error) {

// Error handling}});Copy the code

The logic is done with a flatMap(), which is still a chain. It just looks good, doesn’t it?

2. RxBinding

Rxjava-based Binding is an open source library from Jake Wharton that provides an RXJava-based Binding for the Android platform

API. Binding is the registration of Binding objects such as OnClickListener and TextWatcher

API.

Take an example of setting up click-listening. With RxBinding, event listeners can be set like this:

Button button = ... ; RxView.clickEvents(button)Observable returns click events as an Observable

.subscribe(new Action1<ViewClickEvent>() {

@Override

public void call(ViewClickEvent event) {

// Click handling}});Copy the code

It doesn’t seem to make much difference except in form, and it does in substance. Even if you look at the source code, you’ll see that it doesn’t even implement it

No surprises: inside it is implemented directly with a wrapped setOnClickListener(). However, this is just one

This change in form is exactly what RxBinding is all about: extensibility. Convert click listeners to RxBinding

After Observable, it’s possible to extend it. There are many ways to extend, depending on your needs. One example is the front

The aforementioned throttleFirst(), used to eliminate jitter, that is, the rapid chain of clicks caused by hand shaking:


RxView.clickEvents(button)

.throttleFirst(500, TimeUnit.MILLISECONDS)

.subscribe(clickAction);
Copy the code

3. Various asynchronous operations

The previous examples of Retrofit and RxBinding are two libraries that provide ready-made Observables. And if you have someone

Some asynchronous operations cannot automatically generate observables using these libraries and can write them themselves. For example, database read and write, large picture

All kinds of time-consuming operations that need to be done in the background, such as loading, file compression/decompression, can be done in RxJava, as described in previous chapters

Examples. I don’t think I need to do any more examples here.

4. RxBus

RxBus’s name looks like a library, but it’s not a library, it’s a pattern, and the idea is to implement it using RxJava

EventBus, which eliminates the need to use Otto or GreenRobot EventBus. By the way, Flipboard has replaced Otto with RxBus with no adverse reaction so far.

The last

RxJava is a difficult library for Android developers to get used to because it is so unfamiliar to Android developers

The concept of. But it’s really cool. That’s why I wrote RxJava For Android Developers to get started

Some beginner’s notes for people who don’t know what RxJava is, or for people who are using RxJava but still have doubts

A little bit more in-depth analysis. Anyway, as long as I can give you fellow Android engineers some help, what’s the purpose of this article

That’s it.