Detailed explanation and examples of auxiliary operation of Rxjava2 Observable

Keywords: Mobile Java github

Continue to the previous article: Detailed explanation and examples of auxiliary operation of Rxjava2 Observable (1)

8. TimeInterval

Convert the Observable of the transmitted data to the Observable of the transmitted time interval.

The TimeInterval operator intercepts the data items emitted by the original Observable and replaces them with objects that emit the time interval between adjacent emitters.

This operator converts the original Observable to another Observable, and the latter sends a flag to replace the data item of the former, which represents the length of time passed between two consecutive emitters of the former. The first emitter of the new Observable represents the length of time that elapses between the time the observer subscribes to the original Observable and the time the original Observable launches its first data. There is no emitter corresponding to the time between the original Observable transmitting the last data and transmitting the onCompleted notification.

Example code:

    /**
     * 1. timeInterval(Scheduler scheduler)
     *  scheduler: Optional parameter, specify scheduling thread
     *  Receive the original data item, and launch the object representing the time interval between adjacent emitters
     */
    Observable.intervalRange(1, 10, 100, 100, TimeUnit.MILLISECONDS)
            .timeInterval()
         // . timeInterval(Schedulers.newThread()) / / specifies the worker thread
            .subscribe(new Observer<Timed<Long>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe(1)");
                }

                @Override
                public void onNext(Timed<Long> longTimed) {
                    long time = longTimed.time();           // Interval between consecutive data
                    TimeUnit unit = longTimed.unit();       // Time interval unit between consecutive data
                    Long value = longTimed.value();         // Data item sent by Observable
                    System.out.println("--> onNext(1): " + longTimed.toString());
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError(1): " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete(1)");
                }
            });

    System.in.read();
    System.out.println("-------------------------------------------------");
    /**
     *  2. timeInterval(TimeUnit unit, Scheduler scheduler)
     *  Specify the time interval unit and the specified working thread, receive the original data item, and launch the object representing the time interval of adjacent emitters
     */
    Observable.intervalRange(1, 10, 1000, 1200, TimeUnit.MILLISECONDS)
        //  . timeInterval(TimeUnit.SECONDS) / / specify the time interval unit
            .timeInterval(TimeUnit.SECONDS, Schedulers.newThread())     // Specify interval units and worker threads
            .subscribe(new Observer<Timed<Long>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe(2)");
                }

                @Override
                public void onNext(Timed<Long> longTimed) {
                    System.out.println("--> onNext(2): " + longTimed.toString());
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError(2): " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete(2)");
                }
            });

    System.in.read();

Output:

--> onSubscribe(1)
--> onNext(1): Timed[time=104, unit=MILLISECONDS, value=1]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=2]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=3]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=4]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=5]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=6]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=7]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=8]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=9]
--> onNext(1): Timed[time=100, unit=MILLISECONDS, value=10]
--> onComplete(1)
-------------------------------------------------
--> onSubscribe(2)
--> onNext(2): Timed[time=1, unit=SECONDS, value=1]
--> onNext(2): Timed[time=1, unit=SECONDS, value=2]
--> onNext(2): Timed[time=1, unit=SECONDS, value=3]
--> onNext(2): Timed[time=1, unit=SECONDS, value=4]
--> onNext(2): Timed[time=1, unit=SECONDS, value=5]
--> onNext(2): Timed[time=2, unit=SECONDS, value=6]
--> onNext(2): Timed[time=1, unit=SECONDS, value=7]
--> onNext(2): Timed[time=1, unit=SECONDS, value=8]
--> onNext(2): Timed[time=1, unit=SECONDS, value=9]
--> onNext(2): Timed[time=1, unit=SECONDS, value=10]
--> onComplete(2)

Javadoc: timeInterval()
Javadoc: timeInterval(Scheduler scheduler)
Javadoc: timeInterval(TimeUnit unit)
Javadoc: timeInterval(TimeUnit unit, Scheduler scheduler)

9. Timeout

For an image of the original Observable, if no data is transmitted after a specified time, it will send an error notification.

The implementation in RxJava is the timeout operator with several different variations.

9.1 timeout(timeout, timeUnit)

If the original Observable does not transmit any data after a specified period of time, the Timeout operator will terminate the Observable with an onError notification.

Example code:

    /**
     *  1. timeout(long timeout, TimeUnit timeUnit)
     *  Accept a time parameter. If no data item is sent within the specified time period, an Error notification will be sent,
     *  Or whenever the original Observable sends a piece of data, the timeout starts a timer,
     *  If the timer exceeds the specified time and the original Observable does not transmit another data, 
     *  TimeoutException is thrown to terminate Observable with an error notification.
     */
    Observable.create(new ObservableOnSubscribe<Long>() {
        @Override
        public void subscribe(ObservableEmitter<Long> emitter) throws Exception {
            //  Thread.sleep(2000); / / after a delay of 2 seconds, the data will be transmitted, and a TimeoutException will appear
            emitter.onNext(1L);
            Thread.sleep(2000);     // Data will be sent after 2 seconds delay, and TimeoutException will appear
            emitter.onNext(2L);
            emitter.onComplete();
        }
    }).timeout(1, TimeUnit.SECONDS)     // Specify a timeout period of 1 second
      .subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                System.out.println("--> onSubscribe(1)");
            }

            @Override
            public void onNext(Long aLong) {
                System.out.println("--> onNext(1): " + aLong);
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("--> onError(1): " + e);
            }

            @Override
            public void onComplete() {
                System.out.println("--> onComplete(1)");
            }
      });

    System.in.read();

Output:

--> onSubscribe(1)
--> onNext(1): 1
--> onError(1): java.util.concurrent.TimeoutException: The source did not signal an event for 1 seconds and has been terminated.

Javadoc: timeout(long timeout, TimeUnit timeUnit)

9.2 timeout(timeout, timeUnit, scheduler, other)

After the specified time period, the timeout will switch to use a standby Observable specified by you instead of sending an onError notification. You can specify the worker thread through the scheduler.

Example code:

    /**
     *  2. timeout(long timeout, TimeUnit timeUnit,
     *  Scheduler scheduler,        // Optional parameter, specify thread scheduler
     *  ObservableSource other      // Optional parameter, timeout standby Observable
     *  )
     *
     *  After the specified time period, timeout will switch to use a standby Observable specified by you instead of sending an onError notification.
     */
    Observable.create(new ObservableOnSubscribe<Long>() {
        @Override
        public void subscribe(ObservableEmitter<Long> emitter) throws Exception {
            //  Thread.sleep(2000); / / after a delay of 2 seconds, the data will be transmitted, and a TimeoutException will appear
            emitter.onNext(1L);
            Thread.sleep(2000);     	// Data will be sent after 2 seconds delay, and TimeoutException will appear
            emitter.onNext(2L);
            emitter.onComplete();
        }
    }).timeout(1, TimeUnit.SECONDS,     		// Specify a timeout period of 1 second
            Schedulers.newThread(),             // Specify worker as child
            Observable.just(888L))              // Observable launched by default after timeout
            .subscribe(new Observer<Long>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe(2)");
                }

                @Override
                public void onNext(Long aLong) {
                    System.out.println("--> onNext(2): " + aLong);
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError(2): " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete(2)");
                }
            });
    
    System.in.read();

Output:

--> onSubscribe(2)
--> onNext(2): 1
--> onNext(2): 888
--> onComplete(2)

Javadoc: timeout(long timeout, TimeUnit timeUnit, Scheduler scheduler, ObservableSource other)

9.3 timeout(Function itemTimeoutIndicator, ObservableSource other)

Use a function itemTimeoutIndicator to return an Observable for each item of the original Observable. If the original Observable has not yet transmitted another item of data when the Observable is terminated, it will be considered as a timeout. If there is no other specified for timeout standby, it will throw TimeoutException to terminate bserveable with an error notification. Otherwise, it will be transmitted after timeout Standby Observable.

Example code:

    /**
     *  3. timeout(Function<T, ObservableSource> itemTimeoutIndicator
     *  ObservableSource other      // Optional parameter, standby Observable transmitted after timeout
     *  )
     *  Return an Observable for each item of the original Observable,
     *  If the original Observable does not transmit another data when this Observable terminates, it will be considered as timeout,
     *  If no timeout standby Observable is specified, a TimeoutException is thrown to terminate the Observable with an error notification,
     *  Otherwise, the standby Observable will be launched after timeout.
     */
    Observable.create(new ObservableOnSubscribe<Long>() {
        @Override
        public void subscribe(ObservableEmitter<Long> emitter) throws Exception {
            emitter.onNext(1L);
            Thread.sleep(3000);     // After a delay of 3 seconds, the data will be transmitted, and there will be a TimeoutException
            emitter.onNext(2L);
            emitter.onComplete();
        }
    }).timeout(new Function<Long, ObservableSource<Long>>() {
        @Override
        public ObservableSource<Long> apply(Long aLong) throws Exception {
            // One Observable is sent for each raw data to indicate the Timeout of the next data transmission. Here, the 1 second Timeout is specified
            return Observable.timer(1, TimeUnit.SECONDS);
        }
    }, Observable.just(888L))  // Observable launched by default after timeout
            .subscribe(new Observer<Long>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe(3)");
                }

                @Override
                public void onNext(Long aLong) {
                    System.out.println("--> onNext(3): " + aLong);
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError(3): " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete(3)");
                }
            });

    System.in.read();

Output:

--> onSubscribe(3)
--> onNext(3): 1
--> onNext(3): 888
--> onComplete(3)

Javadoc: timeout(Function<T, ObservableSource> itemTimeoutIndicator)
Javadoc: timeout(Function<T, ObservableSource> itemTimeoutIndicator, ObservableSource other)

10. Timestamp

Attach a specified timestamp to the data item emitted by Observable.

timestamp, which converts an Observable transmitting time type data into an Observable transmitting time type data. Each item contains the original transmitting time information and the original data.

Example code:

    /**
     *  1. timestamp(Scheduler scheduler)
     *  scheduler: Optional parameter, specify thread scheduler
     *
     *  Attach a time stamp to the data item emitted by Observable
     */
    Observable.intervalRange(1, 5, 1, 100, TimeUnit.MILLISECONDS)
            .timestamp(Schedulers.newThread())      // Specifies that processing is scheduled on a child thread
            .subscribe(new Observer<Timed<Long>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe(1)");
                }

                @Override
                public void onNext(Timed<Long> longTimed) {
                    long time = longTimed.time();           // Interval between consecutive data
                    TimeUnit unit = longTimed.unit();       // Time interval unit between consecutive data
                    Long value = longTimed.value();         // Data item sent by Observable
                    System.out.println("--> onNext(1): " + longTimed);
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError(1): " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete(1)");
                }
            });

    System.in.read();
    System.out.println("-------------------------------------------");
    /**
     *  2. timestamp(TimeUnit unit, Scheduler scheduler)
     *  scheduler: Optional parameter, specify thread scheduler
     *
     *  Attach a time stamp information of the specified unit to the data item emitted by Observable
     */
    Observable.intervalRange(1, 5, 1, 1200, TimeUnit.MILLISECONDS)
            .timestamp(TimeUnit.SECONDS, Schedulers.newThread())    // Specify the time unit as seconds, and schedule the processing in the sub thread
            .subscribe(new Observer<Timed<Long>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe(2)");
                }

                @Override
                public void onNext(Timed<Long> longTimed) {
                    System.out.println("--> onNext(2): " + longTimed);
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError(2): " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete(2)");
                }
            });

    System.in.read();

Output:

--> onSubscribe(1)
--> onNext(1): Timed[time=1577455367446, unit=MILLISECONDS, value=1]
--> onNext(1): Timed[time=1577455367545, unit=MILLISECONDS, value=2]
--> onNext(1): Timed[time=1577455367645, unit=MILLISECONDS, value=3]
--> onNext(1): Timed[time=1577455367745, unit=MILLISECONDS, value=4]
--> onNext(1): Timed[time=1577455367845, unit=MILLISECONDS, value=5]
--> onComplete(1)
-------------------------------------------
--> onSubscribe(2)
--> onNext(2): Timed[time=1577455369, unit=SECONDS, value=1]
--> onNext(2): Timed[time=1577455370, unit=SECONDS, value=2]
--> onNext(2): Timed[time=1577455371, unit=SECONDS, value=3]
--> onNext(2): Timed[time=1577455373, unit=SECONDS, value=4]
--> onNext(2): Timed[time=1577455374, unit=SECONDS, value=5]
--> onComplete(2)

Javadoc: timestamp()
Javadoc: timestamp(Scheduler scheduler)
Javadoc: timestamp(TimeUnit unit)
Javadoc: timestamp(TimeUnit unit, Scheduler scheduler)

11. Using

Create a one-time resource that exists only in the Observable lifecycle.

The Using operator allows you to instruct Observable to create a resource that only exists in its life cycle. When the Observable terminates, the resource will be released automatically.

The using operator takes three parameters:

  1. observableFactory: a factory function for users to create one-time assets
  2. resourceFactory: a factory function for creating Observable
  3. disposeFunction: a function used to release resources

When an observer subscribes to the Observable returned by using, using will use the Observable factory function to create the Observable to be observed by the observer, and use the resource factory function to create a resource you want to create. When the observer unsubscribes from the Observable, or when the observer terminates (either normally or by mistake), using uses a third function to release the resources it creates.

Example code:

    /**
     * For resource objects that exist in the lifecycle of Observable
     */
    class MyResource {
        private String resource;

        public MyResource(String resource) {
            this.resource = resource;
        }

        @Override
        public String toString() {
            return "MyResource{" +
                    "resource='" + resource + '\'' +
                    '}';
        }

        public void releaseResource() {
            System.out.println("----> MyResource resource is release. ");
            resource = null;
        }
    }
    
    /**
     *  1. using(Callable resourceSupplier, Function sourceSupplier, Consumer disposer, boolean eager)
     *
     *  resourceSupplier:   // A factory function for users to create one-time resources
     *  sourceSupplier:     // A factory function for creating Observable
     *  disposer:           // A function for releasing resources
     *  eager:              // Optional parameter. If it is true, the processing of the third function, disposer, is executed before the end of Observable
     *
     *  When an observer subscribes to the Observable returned by using, using will use the Observable factory function to create the Observable to be observed by the observer,
     *  Also use the resource factory function to create a resource you want to create.
     *  When the observer unsubscribes from the Observable, or when the observer terminates (either normally or by mistake), 
     *  using Use the third function to release the resources it creates.
     */
    Observable.using(
            // A factory function for users to create one-time resources
            new Callable<MyResource>() {
                @Override
                public MyResource call() throws Exception {
                    System.out.println("----> resourceSupplier call");
                    return new MyResource("This is Observable resource!");
                }
            },
            // A factory function for creating Observable. The Observable returned by this function is the Observable finally observed
            new Function<MyResource, ObservableSource<Long>>() {
                @Override
                public ObservableSource<Long> apply(MyResource myResource) throws Exception {
                    System.out.println("----> sourceSupplier apply: " + myResource);
                    return Observable.rangeLong(1, 5);
                }
            },
            // A function for releasing resources
            new Consumer<MyResource>() {
                @Override
                public void accept(MyResource myResource) throws Exception {
                    System.out.println("----> disposer accept: ");
                    myResource.releaseResource();
                }
            },
            // Optional parameter. If it is true, the function to release resources will be executed before the end of Observable
            true).subscribe(new Observer<Long>() {
                @Override
                public void onSubscribe(Disposable d) {
                    System.out.println("--> onSubscribe");
                }

                @Override
                public void onNext(Long aLong) {
                    System.out.println("--> onNext: " + aLong);
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("--> onError: " + e);
                }

                @Override
                public void onComplete() {
                    System.out.println("--> onComplete");
                }
            });

Output:

----> resourceSupplier call(1)
----> sourceSupplier apply(1): MyResource{resource='This is Observable resource!'}
--> onSubscribe(1)
--> onNext(1): 1
--> onNext(1): 2
--> onNext(1): 3
--> onNext(1): 4
--> onNext(1): 5
----> disposer accept(1): 
----> MyResource resource is release. 
--> onComplete

Javadoc: using(Callable resourceSupplier, Function sourceSupplier, Consumer disposer)
Javadoc: using(Callable resourceSupplier, Function sourceSupplier, Consumer disposer, boolean eager)

12. To

Convert Observable to another object or data structure.

Convert the data sequence emitted by Observable or Observable to another object or data structure. Some of them block until the Observable terminates, and then generate an equivalent object or data structure; others return an Observable that emits that object or data structure.

Because there are many toXXX operator implementations and different variant overloads in rxjava's To operator, we will not expand them in detail here. You can view the official API document See for details.

The following are common To operators:

  • toList(): let Observable combine a number of data into a List, then call the onNext method to pass the entire list.
  • toMap(Function keySelector,Function valueSelector): toMap collects all data items emitted by the original Observable into a Map (the default is HashMap) and then launches the Map. You can provide a function to generate the Key of the Map, as well as a function to convert the data item to the value stored in the Map (the default data item itself is the value).
  • toSortedList(): it will sort the generated list. The default is natural ascending. If the launched data item does not implement the compatible interface, an exception will be thrown. You can also pass a function to compare two data items.
  • To multi Map (function keyselector, function valueselector): similar to toMap, the difference is that the value type of the Map it generates is an ArrayList.

Example code:

        /**
         *  1. toList()
         *  Let Observable combine a number of data into a List, then call the onNext method to pass the entire list.
         */
        range.toList()
                .subscribe(new Consumer<List<Integer>>() {
                    @Override
                    public void accept(List<Integer> integers) throws Exception {
                        System.out.println("--> toList accept(1): " + integers);
                    }
                });

        System.out.println("------------------------------------------");
        /**
         *  2. toMap(Function<? super T, ? extends K> keySelector,Function<? super T, ? extends V> valueSelector)
         *   toMap Collect all data items emitted by the original Observable to a Map (the default is HashMap) and then launch the Map.
         *   You can provide a function to generate the Key of the Map, as well as a function to convert the data item to the value stored in the Map (the default data item itself is the value).
         */
        range.toMap(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return "key" + integer;     // Return a Map key
            }
        }, new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                return integer;             		// Returns the value of a Map
            }
        }).subscribe(new SingleObserver<Map<String, Integer>>() {
            @Override
            public void onSubscribe(Disposable d) {
                System.out.println("--> onSubscribe(2)");
            }

            @Override
            public void onSuccess(Map<String, Integer> stringIntegerMap) {
                System.out.println("--> onSuccess(2): " + stringIntegerMap);
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("--> onError(2): " + e);
            }
        });

        System.out.println("------------------------------------------");
        /**
         *  3. toSortedList()
         *  It will sort the generated list. The default is natural ascending. If the launched data item does not implement the compatible interface, an exception will be thrown.
         *  However, you can also pass a function to compare two data items
         */
        Observable.just(5, 3, 8, 6, 9, 10)
                .toSortedList()
                .subscribe(new SingleObserver<List<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        System.out.println("--> onSubscribe(3)");
                    }

                    @Override
                    public void onSuccess(List<Integer> integers) {
                        System.out.println("--> onSuccess(3): " + integers);
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("--> onError(3): " + e);
                    }
                });

        System.out.println("------------------------------------------");
        /**
         *  4. toSortedList(Comparator comparator)
         *
         *  Passing a function comparator to compare two data items sorts the resulting list
         */
        Observable.just(5, 3, 8, 6, 9, 10)
                .toSortedList(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        System.out.println("--> compare: o1 = " + o1 + ", o2 = " + o2);
                        return o1 - o2;     // Sorting logic of comparator
                    }
                }).subscribe(new SingleObserver<List<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        System.out.println("--> onSubscribe(4)");
                    }

                    @Override
                    public void onSuccess(List<Integer> integers) {
                        System.out.println("--> onSuccess(4): " + integers);
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("--> onError(4): " + e);
                    }
                });

        System.out.println("------------------------------------------");
        /**
         *  5. toMultimap(Function<T, K> keySelector, Function<T, V> valueSelector)
         *  Similar to toMap, the difference is whether the value type of the Map it generates is an ArrayList
         */
        range.toMultimap(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return "key" + integer;     // Return a Map key
            }
        }, new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) throws Exception {
                return integer;            		 // Returns the value of a Map
            }
        }).subscribe(new SingleObserver<Map<String, Collection<Integer>>>() {
            @Override
            public void onSubscribe(Disposable d) {
                System.out.println("--> onSubscribe(5)");
            }

            @Override
            public void onSuccess(Map<String, Collection<Integer>> stringCollectionMap) {
                System.out.println("--> onSuccess(5): " + stringCollectionMap);
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("--> onError(5): " + e);
            }
        });

Output:

--> toList accept(1): [1, 2, 3, 4, 5]
------------------------------------------
--> onSubscribe(2)
--> onSuccess(2): {key1=1, key2=2, key5=5, key3=3, key4=4}
------------------------------------------
--> onSubscribe(3)
--> onSuccess(3): [3, 5, 6, 8, 9, 10]
------------------------------------------
--> onSubscribe(4)
--> compare: o1 = 3, o2 = 5
--> compare: o1 = 8, o2 = 3
--> compare: o1 = 8, o2 = 5
--> compare: o1 = 6, o2 = 5
--> compare: o1 = 6, o2 = 8
--> compare: o1 = 9, o2 = 6
--> compare: o1 = 9, o2 = 8
--> compare: o1 = 10, o2 = 6
--> compare: o1 = 10, o2 = 9
--> onSuccess(4): [3, 5, 6, 8, 9, 10]
------------------------------------------
--> onSubscribe(5)
--> onSuccess(5): {key1=[1], key2=[2], key5=[5], key3=[3], key4=[4]}

Javadoc: toList()
Javadoc: toMap(Function keySelector,Function valueSelector)
Javadoc: toSortedList()
Javadoc: toMultimap(Function keySelector, Function valueSelector)

Summary

This section mainly introduces various auxiliary operators in Rxjava, such as delay, timeout, event monitoring and other auxiliary operations, which are very useful in development.

Tip: Rxjava2 version used above: 2.2.12

Rx introduction and explanation and complete catalog reference: Rxjava2 introduction and detailed examples

Instance code:

Posted by gapern on Mon, 06 Jan 2020 09:18:47 -0800