[good book sharing: Spring responsive programming -- JD]
2.2 practice of using RxJava responsive framework
RxJava library is the Java virtual machine implementation of Reactive Extensions, which is similar to the combination of observer mode, iterator mode and functional programming.
2.2.1 responsive flow = observer + iterator
Separate producers and consumers through events.
Iterator pattern: a scenario where the producer is not expected to produce data before the consumer appears.
public interface Iterator<T> { T next(); boolean hasNext(); } // Combined observer public interface RxObserver<T> { void onNext(T next); // Notify new value void onComplete(); // End of notification void onError(Exception e); // Notification error }
RxObserver is similar to the Observer in the Observer mode described earlier.
For subscribed content and subscribers, we can define Observale and Subcriber
- Observable: similar to the Subject in the observer mode, it is an observable event source. It will emit elements, and there are flow conversion methods and flow initialization factory methods.
- Subscriber: abstract class, which is used to implement the interface of Observer and consumer element, and is the basis of the implementation class
At the same time, we define subscription to control the runtime relationship between Observable and Subscriber. Subscription can check the subscription status and cancel the subscription if necessary.
The subscription contract between producer and consumer is as follows:
---------| — onNext —> | -----------
| Observable | – onComplete -> | Observer |
--------- | — onError —> |------------
According to the rules in RxJava, the Observable event source can send 0-N elements to indicate the end by declaring success and raising an error.
So the Observable event source calls onNext to the associated Subscriber many times, and finally calls onComplete or onError.
2.2.2 production and consumption flow data
Observable is regarded as an event generator, which will propagate events to subscribers during subscription.
Observable<String> observable = Obervable.create( new Observable.OnSubcribe<String>(){ @Override public void call(Subcriber<? super String> sub){ sub.onNext("Hello, reactive world!"); sub.onCompleted(); } } ); // call() is triggered immediately when the subscriber appears // lambda writing Observable<String> observable = Obervable.create( sub -> { sub.onNext("Hello, reactive world!"); sub.onCompleted(); } );
Observable is reusable, and each subscriber will receive this message event immediately after subscribing. Starting with RxJava 1.2.7, the creation of observable is discarded because it is unsafe because it may generate too many elements, resulting in excessive load on subscribers. That is, this method does not support back pressure.
The corresponding subscriber code is as follows:
Subcriber<String> subscriber = new Subcriber<String>(){ @Override public void onNext(String s){ System.out.println("receive: " + s); } @Override public void onCompleted(){ System.out.println("Done."); } @Override public void onError(Throwable e){ System.err.println(e); } }
So now the subscriber subcriber and the message source Observable can work together. Subcriber must implement the Observer observer method, define onNext to respond to new events, onCompleted to respond to flow completion, and onError to respond to errors.
Finally, just add a subscription relationship in Observable to complete the responsive demo program.
observable.subscribe(subcriber); // output: // receive: Hello, reactive world! // Done. // More simplified lambda writing Observable<String> observable = Obervable.create( sub -> { sub.onNext("Hello, reactive world!"); sub.onCompleted(); } ); observable.subscribe( s -> System.out.println("receive: " + s), () -> System.out.println("Done"), System.err::println; ); // output: // receive: Hello, reactive world! // Done.
The Rxjava library is flexible for creating Observable instances of message sources.
Observable.just("1","2","3","4"); Observable.from(new String[]{"A", "B", "C", "D"}); Observable.from(Collections.emptyList()); Observale<String> msg1 = Observable.fromCallable(()->"hello-"); Future<String> future = Executors.newCachedThreadPool().submit(() -> "world"); Observale<String> msg2 = Observable.from(future); //Combine multiple streams in order of parameters Observale<String> msg = Observable.concat(msg1, msg2, Observable.just(".")); msg.forEach(System.out::print); // output: hello-world.
Although there is an onError signal to handle errors, it seems that there is no need to define a handler for exceptions, the default Subscriber implementation will still throw an rx.exceptions.OnErrorNotImplementedException when an error occurs