RxJava——操作符详解(四)

RxJava操作符详解(四)

七、条件操作符

操作符 描述
all 判断是否所有发射的数据都满足指定条件
amb 在多个Observable中选择第一个发射数据的Observable
contains 检查流中是否包含指定元素
isEmpty 检查流是否为空
defaultIfempty 如果源Observable为空,发射一个默认值
switchIfEmpty 如果源Observable为空,切换到另一个Observable
sequenceEqual 比较两个Observable发射的数据序列是否相同
skipUntil 跳过源Observable的数据,直到另一个Observable开始发射
takeUntil 获取源Observable的数据,直到另一个Observable开始发射
skipWhile 当条件为true时跳过,条件为false时开始接收
takeWhile 当条件为true时接收,条件为false时停止

7.1、all

al操作符根据一个函数对源Observable发送的所有数据进行判断,最终返回的结果就是这个判断结果。这个函数使用源Observable发送的数据作为参数,内部判断所有的数据是否满足我们定义好的判断条件,如果全部都满足则返回true,否则就返回false,其示意图如图所示。

下面创建两个Observable,.一个发送15的整数,另一个发送16的整数,然后使用all操作符进行判断,如代码所示。`

java 复制代码
@Test
public void testAll() {
    Observable.just(1, 2, 3, 4, 5)
            .all(i -> i < 6)
            .subscribe(e -> System.out.println("all:" + e));

    Observable.just(1, 2, 3, 4, 5, 6)
            .all(i -> i < 6)
            .subscribe(e -> System.out.println("not all:" + e));
}


all:true
not all:false

7.2、amb

amb是 "ambiguous"(模糊的)的缩写,用于在多个Observable中选择第一个发射数据的Observable,忽略其他所有Observable。

amb操作符可以将至多9个Observable结合起来,让它们竞争。哪个Observable首先发送了数据(包括onError和onComplete),就继续发送这个Observable的数据,其他Observable所发送的数据都会被丢弃,其示意图如图所示。

7.2.1、操作符变体

Observable.amb():接收一个Observable的可迭代集合

java 复制代码
@Test
public void testAmb() {
    List<Observable<String>> observables = Arrays.asList(
            Observable.timer(2, TimeUnit.SECONDS).map(i -> "Source 1"),
            Observable.timer(1, TimeUnit.SECONDS).map(i -> "Source 2"),
            Observable.timer(3, TimeUnit.SECONDS).map(i -> "Source 3")
    );

    Observable.amb(observables)
            .subscribe(
                    data -> System.out.println("Received: " + data),
                    error -> System.out.println("Error: " + error),
                    () -> System.out.println("Completed")
            );

        // 输出: Received: Source 2
        // 只有第二个Observable的数据会被接收

    try {
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Received: Source 2
Completed

Observable.ambArray():接收可变参数的Observable数组

java 复制代码
Observable<String> source1 = Observable.timer(500, TimeUnit.MILLISECONDS)
    .map(i -> "Fast Source (500ms)");
Observable<String> source2 = Observable.timer(200, TimeUnit.MILLISECONDS)
    .map(i -> "Faster Source (200ms)");
Observable<String> source3 = Observable.timer(1000, TimeUnit.MILLISECONDS)
    .map(i -> "Slow Source (1000ms)");

Observable.ambArray(source1, source2, source3)
    .subscribe(data -> System.out.println("Winner: " + data));
// 输出: Winner: Faster Source (200ms)

ambWith():实例方法,用于与另一个Observable竞争

java 复制代码
Observable<String> mainSource = Observable.create(emitter -> {
    new Thread(() -> {
        Thread.sleep(300);
        emitter.onNext("Main Source");
        emitter.onComplete();
    }).start();
});

Observable<String> backupSource = Observable.create(emitter -> {
    new Thread(() -> {
        Thread.sleep(200);
        emitter.onNext("Backup Source");
        emitter.onComplete();
    }).start();
});

mainSource.ambWith(backupSource)
    .subscribe(winner -> System.out.println("Selected: " + winner));
// 输出: Selected: Backup Source

7.2.2、不同类型Observable的行为

1. 立即发射的Observable

java 复制代码
Observable<String> immediate = Observable.just("Immediate");
Observable<String> delayed = Observable.timer(1, TimeUnit.SECONDS)
    .map(i -> "Delayed");

Observable.ambArray(immediate, delayed)
    .subscribe(System.out::println);  // 输出: Immediate

2. 空的Observable

java 复制代码
// 空Observable永远不会被选择,因为它从不发射
Observable<String> empty = Observable.empty();
Observable<String> hasData = Observable.just("Has Data");

Observable.ambArray(empty, hasData)
    .subscribe(System.out::println);  // 输出: Has Data

3. 立即结束的Observable(empty/error)

java 复制代码
Observable<String> immediateError = Observable.error(
    new RuntimeException("Error immediately")
);
Observable<String> normalSource = Observable.timer(100, TimeUnit.MILLISECONDS)
    .map(i -> "Normal Data");

Observable.ambArray(immediateError, normalSource)
    .subscribe(
        data -> System.out.println("Data: " + data),
        error -> System.out.println("Error caught: " + error.getMessage())
    );
// 输出: Error caught: Error immediately
// 错误会被立即传播

7.2.3、实际应用场景

1. 多数据源竞速(冗余请求)

java 复制代码
public Observable<Response> loadDataWithRedundancy() {
    // 多个相同功能的数据源
    Observable<Response> source1 = apiService.getDataFromPrimary()
        .subscribeOn(Schedulers.io());
    
    Observable<Response> source2 = apiService.getDataFromBackup1()
        .subscribeOn(Schedulers.io());
    
    Observable<Response> source3 = apiService.getDataFromBackup2()
        .subscribeOn(Schedulers.io());
    
    return Observable.ambArray(source1, source2, source3)
        .timeout(3, TimeUnit.SECONDS, Observable.error(new TimeoutException()));
}

2. 缓存优先策略

java 复制代码
public Observable<Data> loadDataWithCacheFirst() {
    Observable<Data> memoryCache = loadFromMemoryCache();
    Observable<Data> diskCache = loadFromDiskCache();
    Observable<Data> network = loadFromNetwork();
    
    return Observable.ambArray(
        memoryCache,  // 内存最快
        diskCache,    // 其次磁盘
        network       // 最后网络
    ).firstElement()
     .toObservable();
}

3. 服务健康检查

java 复制代码
public Observable<Server> findHealthyServer(List<Server> servers) {
    List<Observable<Server>> healthChecks = servers.stream()
        .map(server -> checkServerHealth(server)
            .filter(healthy -> healthy)
            .map(healthy -> server)
            .timeout(2, TimeUnit.SECONDS, Observable.empty())
        )
        .collect(Collectors.toList());
    
    return Observable.amb(healthChecks)
        .firstElement()
        .toObservable();
}

private Observable<Boolean> checkServerHealth(Server server) {
    return apiClient.ping(server)
        .map(response -> response.isSuccessful())
        .onErrorReturnItem(false)
        .subscribeOn(Schedulers.io());
}

7.2.4、高级用法和模式

1. 带标签的数据源

java 复制代码
class SourceResult {
    final String source;
    final String data;
    
    SourceResult(String source, String data) {
        this.source = source;
        this.data = data;
    }
}

public Observable<SourceResult> loadFromFastestSource() {
    Observable<SourceResult> sourceA = apiA.getData()
        .map(data -> new SourceResult("API_A", data))
        .subscribeOn(Schedulers.io());
    
    Observable<SourceResult> sourceB = apiB.getData()
        .map(data -> new SourceResult("API_B", data))
        .subscribeOn(Schedulers.io());
    
    Observable<SourceResult> sourceC = cache.getData()
        .map(data -> new SourceResult("CACHE", data))
        .subscribeOn(Schedulers.io());
    
    return Observable.ambArray(sourceA, sourceB, sourceC);
}

2. 组合使用其他操作符

java 复制代码
Observable.ambArray(
    apiCall1.timeout(2, TimeUnit.SECONDS),
    apiCall2.timeout(2, TimeUnit.SECONDS),
    Observable.just("Fallback").delay(3, TimeUnit.SECONDS)
)
.filter(data -> !data.isEmpty())
.firstElement()
.toObservable()
.subscribe(
    data -> System.out.println("Got: " + data),
    error -> System.out.println("All failed"),
    () -> System.out.println("Completed")
);

3. 动态构建amb

java 复制代码
public Observable<String> raceConditions(List<Supplier<Observable<String>>> suppliers) {
    List<Observable<String>> observables = suppliers.stream()
        .map(supplier -> Observable.fromCallable(() -> supplier.get())
            .flatMap(obs -> obs)
            .subscribeOn(Schedulers.io())
        )
        .collect(Collectors.toList());
    
    return Observable.amb(observables);
}

7.3、contains

contains操作符用来判断源Observable所发送的所有数据是否包含某一个数据,如果包含则返回true;如果源Observable已经结束了却还没有发送这个数据,则返回false。所以在

Observable没发送完所有的数据之前,contains是不会有返回数据的,其示意图如图所示。

创建两个相同的Observable,.发送1~3的整数,然后分别用contains操作符判断它们所发送的数据里是否包含3和4,如代码所示。

java 复制代码
@Test
public void testContains() {
    Observable.just(1, 2, 3)
            .contains(3)
            .subscribe(e -> System.out.println("contains:" + e));

    Observable.just(1, 2, 3)
            .contains(4)
            .subscribe(e -> System.out.println("notcontains:" + e));
}

contains:true
notcontains:false

7.4、isEmpty

isEmpty操作符用来判断源Observable是否发送过数据,如果发送过就会返回false;如果源Observable已经结束了都还没有发送这个数据,则返回true,其示意图如图所示。

创建一个Observable,让它在不发送任何数据的情况下结束,然后使用isEmpty操作符判、断其是否为空,如代码所示。

java 复制代码
@Test
public void testIsEmpty() {
    Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onComplete();
        }
    }).isEmpty().subscribe(e -> System.out.println("isEMpty:" + e));
}

isEMpty:true

订阅后输出了true,说明我们刚刚创建的Observable确实是一个空的Observable。

7.5、defaultIfEmpty

defaultIfEmpty操作符会判断源Observable是否发送了数据,如果源Observable发送了数据,则正常发送这些数据;否则发送一个默认的数据,其示意图如图所示。

下面创建一个空的Observable和一个非空的Observable,.分别用defaultIfEmpty操作符处理,如果为空则发送出数据10,如代码所示。

java 复制代码
@Test
public void testDefaultEmpty() {
    Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onComplete();
        }
    }).defaultIfEmpty(10).subscribe(e -> System.out.println("empty:" + e));

    Observable.just(1).defaultIfEmpty(10)
            .subscribe(e -> System.out.println("notEmpty:" + e));
}

empty:10
notEmpty:1

订阅后输出结果如下。因为第一个Observable为空,所以defaultIfEmpty将数据l0发送了出来;而第二个Observable发送了数据1,不为空,所以正常发送数据。

7.6、switchIfEmpty

如果源Observable为空,切换到另一个Observable

java 复制代码
@Test
public void testSwitchIfEmpty() {
    Observable.empty()
            .switchIfEmpty(Observable.just(1, 2, 3))
            .subscribe(System.out::println);
}

1
2
3

7.7、sequenceEqual

sequenceEqual操作符用来判断两个Observable发送的数据序列是否相同(发送的数据相同、数据的序列相同、结束的状态相同),如果全部相同则返回true,否则返回false,其示意图如图所示。

下面使用sequenceEqual操作符分别来比较两个发送数据相同的Observable和两个发送数据不同的Observable,如代码所示,然后订阅查看结果。

java 复制代码
@Test
public void testSequenceEqual() {
    Observable.sequenceEqual(Observable.just(1, 2, 3),
            Observable.just(1, 2, 3))
            .subscribe(e -> System.out.println("equal:" + e));

    Observable.sequenceEqual(Observable.just(1, 2, 3),
            Observable.just(1, 2))
            .subscribe(e -> System.out.println("notEqual:" + e));
}

equal:true
notEqual:false

订阅后的输出结果如下。可以看到sequenceEqual操作符将两组Observable的比较结果正确地输出了出来。

7.8、skipUntil和skipWhile

这两个操作符都是根据条件来跳过一些数据,不同之处在于skipUntil是根据一个标志Observable来判断的,当这个标志Observable没有发送数据的时候,所有源Observable发送的数据都会被跳过;当标志Observable发送了一个数据后,则开始正常地发送数据。其示意图如图所示。

而skip While则是根据一个函数来判断是否跳过数据,如果函数返回值为true,则一直跳过源Observable发送的数据;如果函数返回false,则开始正常发送数据,其示意图如图所示。

下面使用interval操作符创建两个操作符,每隔一秒发送一个数据。然后分别用skipUntil和skip While来跳过一些数据,如代码所示。

java 复制代码
@Test
public void testSkip() {
    Observable.interval(1, TimeUnit.SECONDS)
            .skipUntil(Observable.timer(3, TimeUnit.SECONDS))
            .subscribe(e -> System.out.println("skipUntil:" + e));

    Observable.interval(1, TimeUnit.SECONDS)
            .skipWhile(l -> l < 5)
            .subscribe(e -> System.out.println("skipWhile:" + e));

    try {
        Thread.sleep(9000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

skipUntil:3
skipUntil:4
skipUntil:5
skipWhile:5
skipUntil:6
skipWhile:6
skipUntil:7
skipWhile:7
skipWhile:8
skipUntil:8

订阅后的输出结果如下。对于第一个Observable,我们采用了timer操作符来创建标志Observable,所以跳过了源Observable的前两个数据;对于第二个Observable,我们的条件是小于5的数据都跳过,所以最终的数据是过了5秒后从5开始发送出来。

7.9、takeUntil和takeWhile

takeUntil和takeWhile操作符分别和skipUnitl及skipWhile操作符是完全相反的功能。takeUntil也是使用一个标志Observable是否发送数据来进行判断:当标志Observable没有发送数据时,正常发送数据,而一旦标志Observable发送过了数据,则后面的数据都会被丢弃,其示意图如图所示。

take While则是根据一个函数来判断是否发送数据,当函数返回值为true的时候正常发送数据;当函数返回值为flse的时候丢弃其后面所有的数据。其示意图如图所示。

下面使用interval操作符创建两个Observable,分别使用takeUntil和takeWhile操作符来取数据,如代码所示。

java 复制代码
@Test
public void testTake() {
    Observable.interval(1, TimeUnit.SECONDS)
            .takeUntil(Observable.timer(3, TimeUnit.SECONDS))
            .subscribe(e -> System.out.println("takeUntil:" + e));

    Observable.interval(1, TimeUnit.SECONDS)
            .takeWhile(l -> l < 5)
            .subscribe(e -> System.out.println("takeWhile:" + e));

    try {
        Thread.sleep(9000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

takeUntil:0
takeWhile:0
takeUntil:1
takeWhile:1
takeUntil:2
takeWhile:2
takeWhile:3
takeWhile:4

订阅后输出的结果如下。可以看到第一个Observable因为使用timer创建标志Observable,所以只取了前两个数;第二个Observable只能把小于5的数据发送出来,大于5的数据都被丢弃了。

7.10、条件操作符使用场景

7.10.1、数据验证

java 复制代码
// 验证所有数据都满足条件
dataSource
    .all(this::isValid)
    .subscribe(valid -> {
        if (valid) {
            processData();
        } else {
            showError("数据不合法");
        }
    });

7.10.2、回退机制

java 复制代码
// 主数据源失败时使用备用源
getDataFromApi()
    .switchIfEmpty(getDataFromCache())
    .defaultIfEmpty("No data available")
    .subscribe(this::displayData);

7.10.3、竞态条件处理

java 复制代码
// 多个数据源竞速,使用最快的
Observable<Data> api1 = getFromApi1();
Observable<Data> api2 = getFromApi2();
Observable<Data> cache = getFromCache();

Observable.ambArray(api1, api2, cache)
    .firstElement()
    .subscribe(this::processData);

7.10.4、条件过滤

java 复制代码
// 根据条件动态过滤
dataStream
    .skipUntil(userActionObservable)  // 等待用户操作
    .takeWhile(data -> !data.isComplete())  // 直到完成
    .subscribe(this::processData);

八、聚合操作符

8.1、concat

concat操作符将多个Observable结合成一个Observable并发送数据,并且严格按照先后顺序发送数据,即前一个Observable的数据没有发送完时,后面的Observable是不能发送数据的。其示意图如图所示。

有两个操作符与concat操作符很类似,它们分别是:

  • startWith:仅仅是在前面插上一个Observable或者一些数据,并且先发送插入的内容。
  • merge:其发送的数据是无序的,也就是说被组合的多个Observable是可以自由发送数据的,而不用管其他Observable的状态。

代码将使用just操作符创建三个Observable,发送不同的数据,然后使用concat操作符将其组合起来并进行订阅。

java 复制代码
@Test
public void testConcat() {
     Observable<Integer> o1 = Observable.just(1, 2, 3);
     Observable<Integer> o2 = Observable.just(4, 5, 6);
     Observable<Integer> o3 = Observable.just(7, 8, 9);

     Observable.concat(o1, o2, o3)
             .subscribe(e -> System.out.println("concat:" + e));
}

concat:1
concat:2
concat:3
concat:4
concat:5
concat:6
concat:7
concat:8
concat:9

订阅后的结果如下。可以看到,所有的Observable严格按照组合时的顺序来发送数据,只有前一个Observable发送完所有的数据时,后一个Observable才开始发送数据。

8.2、count

count操作符用来统计源Observable发送了多少个数据,最后将数目发送出来。如果源Observable发送错误,则会将错误直接报出来。在源Observable停止发送前,count是不会发送统计数据的,其示意图如图所示。

java 复制代码
@Test
public void testCount() {
    Observable.just(1, 2, 3)
            .count()
            .subscribe(e -> System.out.println("count:" + e ));
}

count:3

8.3、reduce

reduce操作符应用一个函数接收Observable发送的数据和函数的计算结果,作为下次计算的参数,并输出最后的结果。reduce与我们前面了解过的scan操作符很类似,只是scan会输出每次计算的结果,而reduce只输出最后的结果。reduce的示意图如图所示。

我们首先创建一个包含10个2的list,然后使用from操作符以这个1ist为基础创建一个发送l0个2的Observable,并使用reduce操作符来计算最后的结果,如代码所示。

java 复制代码
@Test
public void testReduce() {
    ArrayList<Integer> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add(2);
    }
    Observable.fromIterable(list)
            .reduce((x, y) -> x + y)
            .subscribe(e -> System.out.println("reduce:" + e));
}

reduce:20
java 复制代码
// 基本用法
Observable.range(1, 5)
    .reduce(0, (sum, item) -> sum + item)
    .subscribe(result -> System.out.println("Sum: " + result));
// 输出: Sum: 15

// 无初始值
Observable.range(1, 5)
    .reduce((a, b) -> a + b)
    .subscribe(result -> System.out.println("Sum: " + result.get()));
// 输出: Sum: 15

8.4、collect

collect操作符类似于reduce,但是二者目的不同。collect操作符用来将源Observable发送的数据收集到一个数据结构里面,最后将这个数据结构整个发送出来。collect操作符需要使用

两个函数作为参数:

  • 第一个函数会产生收集数据结构的函数。
  • 第二个函数会将上面函数产生的数据结构和源Observable发送的数据作为参数,且这个函数会将源Observable发送的数据存入到这个数据结构中。

collect操作符的示意图如图所示。

java 复制代码
@Test
public void tstCollect() {
    ArrayList<Integer> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add(2);
    }
    Observable.fromIterable(list)
            .collect(() -> new ArrayList(), new BiConsumer<ArrayList, Integer>() {
                @Override
                public void accept(ArrayList arrayList, Integer integer) throws Exception {
                    arrayList.add(integer);
                }
            })
            .subscribe(e -> System.out.println("collect:" + e));
}

collect:[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

8.5、容器聚合操作符

8.5.1、toList

  • 功能:收集所有数据到List
  • 返回:Single<List>
java 复制代码
Observable.just("Apple", "Banana", "Cherry")
    .toList()
    .subscribe(list -> System.out.println("List: " + list));
// 输出: List: [Apple, Banana, Cherry]

// 指定容量
Observable.range(1, 1000)
    .toList(100)  // 初始容量
    .subscribe(list -> System.out.println("Size: " + list.size()));

8.5.2、toSortedList

java 复制代码
Observable.just(5, 3, 9, 1, 7)
    .toSortedList()
    .subscribe(sorted -> System.out.println("Sorted: " + sorted));
// 输出: Sorted: [1, 3, 5, 7, 9]

// 自定义排序
Observable.just("Banana", "Apple", "Cherry")
    .toSortedList(Comparator.reverseOrder())
    .subscribe(sorted -> System.out.println("Reverse sorted: " + sorted));
// 输出: Reverse sorted: [Cherry, Banana, Apple]

8.5.3、toMap

java 复制代码
Observable<User> users = Observable.just(
    new User(1, "Alice"),
    new User(2, "Bob"),
    new User(3, "Charlie")
);

// 简单toMap
users.toMap(User::getId)
    .subscribe(map -> System.out.println("User Map: " + map));
// 输出: {1=User{1, Alice}, 2=User{2, Bob}, 3=User{3, Charlie}}

// 指定value转换
users.toMap(
        User::getId,
        User::getName
    )
    .subscribe(map -> System.out.println("ID-Name Map: " + map));
// 输出: {1=Alice, 2=Bob, 3=Charlie}

8.5.4、toMultimap

java 复制代码
Observable<Student> students = Observable.just(
    new Student("Math", "Alice"),
    new Student("Math", "Bob"),
    new Student("Science", "Charlie"),
    new Student("Math", "David")
);

// 创建Map<String, List<Student>>
students.toMultimap(
        Student::getSubject,
        Student::getName
    )
    .subscribe(map -> {
        System.out.println("Students by subject:");
        map.forEach((subject, names) -> 
            System.out.println("  " + subject + ": " + names));
    });
// 输出:
// Students by subject:
//   Math: [Alice, Bob, David]
//   Science: [Charlie]

九、Connectable Observable相关操作符

首先我们来回顾一下前面所学的Observable,它们有一个共性,那就是只有当订阅者来订阅时才会开始发送数据,否则什么也不会发生,这就是懒加载。那什么是Connectable Observable呢?它是一种特殊的Observable,并不是在订阅者订阅时才发送数据,而是只要对其应用connect操作符就开始发送数据。所以如果在对其应用connect操作符之前进行订阅的话,并不能让Connectable Observable发送数据。

9.1、publish和connect

publish操作符就是用来将一个普通的Observable转化为一个Connectable Observable的。需要注意的是,如果发送数据已经开始了再进行订阅的话,就只能接收以后发送的数据。其示意图如图所示。

connect操作符就是用来触发Connectable Observable发送数据的。应用connect操作符后会返回一个Subscription对象,通过这个Subscription对象,我们可以调用其unsubscribe方法来中止数据的发送。另外,如果还没有订阅者订阅就应用connect操作符,也是可以使其开始发送数据的。

下面使用interval操作符创建一个Observable,.它每隔一秒发送一个数据,然后使用publish操作符将其转化为一个Connectable Observable。然后创建两个订阅者,让订阅者1订阅到前面创建的Connectable Observable,并且监控发送的数据,当数据为3时把订阅者2也订阅上,如代码所示。

java 复制代码
@Test
public void testPublish() {
    ConnectableObservable<Long> obser = Observable.interval(1, TimeUnit.SECONDS)
            .observeOn(Schedulers.newThread())
            .publish();

    obser.subscribe(e -> {
        System.out.println("consumer1:" + e);
        if (e == 3)
            obser.subscribe(l -> System.out.println("consumer2:" + l));
    });

    obser.connect();


    try {
        Thread.sleep(6000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}


consumer1:0
consumer1:1
consumer1:2
consumer1:3
consumer1:4
consumer2:4
consumer1:5
consumer2:5

9.2、refCount

refCount操作符能够将一个Connectable Observable对象再重新转化为一个普通的Observable对象,这时候如果有订阅者进行订阅将会触发数据的发送,其示意图如图所示。

如代码所示,我们首先如上文一样使用publish创建一个Connectable Observable对象,然后再使用ref℃ount将其转化为一个普通的Observable对象,最后对其进行订阅。

java 复制代码
@Test
public void testRefCount() {
    Observable.interval(1, TimeUnit.SECONDS)
            .observeOn(Schedulers.newThread())
            .publish()
            .refCount()
            .subscribe(e -> System.out.println("refCount:" + e));

    try {
        Thread.sleep(6000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}


refCount:0
refCount:1
refCount:2
refCount:3
refCount:4
refCount:5
相关推荐
我是阿亮啊2 小时前
Android Handler 消息机制之 Looper 深度解析
android·loop·handler·looper
Mr YiRan2 小时前
Android 16KB 腾讯Mars XLog适配
android
2501_915921432 小时前
不用 Xcode 上架 iOS,拆分流程多工具协作完成 iOS 应用的发布准备与提交流程
android·macos·ios·小程序·uni-app·iphone·xcode
子木鑫3 小时前
[SUCTF2019 & GXYCTF2019] 文件上传绕过实战:图片马 + .user.ini / .htaccess 构造 PHP 后门
android·开发语言·安全·php
一起养小猫3 小时前
Flutter for OpenHarmony 实战:打造功能完整的记账助手应用
android·前端·flutter·游戏·harmonyos
_乐无3 小时前
Unity 发布 Android 安卓端所有文件可读写
android·unity·游戏引擎
User_芊芊君子3 小时前
【LeetCode原地复写零】:双指针+逆向填充,O(n)时间O(1)空间最优解!
android·linux·leetcode
2501_944448005 小时前
Flutter for OpenHarmony衣橱管家App实战:支持我们功能实现
android·javascript·flutter
2601_9498333914 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter