RxJava usage scenarios

This blog mainly discusses some commonly used scenarios of RxJava. Most of the examples are taken from my own experience, and you are welcome to add them.

Scenarios when fetching data and checking the cache first

A scenario we often encounter is that when acquiring data, first check whether there is cached data in the cache, and if so, return the data in the cache, otherwise, re-pull the data from the data source.

Using RxJava's concat+first operator can easily satisfy this scenario.

final Observable<String> memory = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        if (memoryCache != null) {
            subscriber.onNext(memoryCache);
        } else {
            subscriber.onCompleted();
        }
    }
});
Observable<String> disk = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        String cachePref = rxPreferences.getString("cache").get();
        if (!TextUtils.isEmpty(cachePref)) {
            subscriber.onNext(cachePref);
        } else {
            subscriber.onCompleted();
        }
    }
});

Observable<String> network = Observable.just("network");

//主要就是靠concat operator来实现
Observable.concat(memory, disk, network)
.first()
.subscribeOn(Schedulers.newThread())
.subscribe(s -> {
    memoryCache = "memory";
    System.out.println("--------------subscribe: " + s);
});

What if the effect we want is to first fetch the data from the cache, display it, and then re-pull the data from the data source, and then display it? It's still very simple, just remove the first. concat can guarantee that two Observables are executed in order.

The interface needs to wait until multiple interfaces and fetch data before updating

In many cases, all the data of one interface is not returned by one interface. The client may need to call multiple interfaces concurrently, and then wait for the data of these interfaces to be returned before displaying.
RxJava's merge operator can meet this need.

//拼接两个Observable的输出,不保证顺序,按照事件产生的顺序发送给订阅者
private void testMerge() {
    Observable<String> observable1 = DemoUtils.createObservable1().subscribeOn(Schedulers.newThread());
    Observable<String> observable2 = DemoUtils.createObservable2().subscribeOn(Schedulers.newThread());

    Observable.merge(observable1, observable2)
            .subscribeOn(Schedulers.newThread())
            .subscribe(System.out::println);
}

Of course, a defect of merge is that it requires the data types in the two Observables to be the same. The scenario just mentioned may be a bit difficult, so we can consider using the zip operator,
zip and to force the requirements in multiple Observables. The data types are consistent.

A request from one interface depends on the data returned by another API request

For example, we often need to log in to get the message list according to the token obtained.

Here, RxJava is mainly used to solve the problem of nested callbacks. There is a proper noun called Callback hell .

NetworkService.getToken("username", "password")
    .flatMap(s -> NetworkService.getMessage(s))
    .subscribe(s -> {
        System.out.println("message: " + s);
    });

Interface buttons need to prevent continuous clicks

RxView.clicks(findViewById(R.id.btn_throttle))
    .throttleFirst(1, TimeUnit.SECONDS)
    .subscribe(aVoid -> {
        System.out.println("click");
    });

Responsive interface

For example, if a checkbox is checked, the corresponding preference is automatically updated.

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
RxSharedPreferences rxPreferences = RxSharedPreferences.create(preferences);

Preference<Boolean> checked = rxPreferences.getBoolean("checked", true);

CheckBox checkBox = (CheckBox) findViewById(R.id.cb_test);
RxCompoundButton.checkedChanges(checkBox)
        .subscribe(checked.asAction());

complex data transformation

Observable.just("1", "2", "2", "3", "4", "5")
    .map(Integer::parseInt)
    .filter(s -> s > 1)
    .distinct()
    .take(3)
    .reduce((integer, integer2) -> integer.intValue() + integer2.intValue())
    .subscribe(System.out::println);//9

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327058842&siteId=291194637