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
相关推荐
莞凰1 天前
昇腾CANN的“灵脉根基“:Runtime仓库探秘
android·人工智能·transformer
NiceCloud喜云1 天前
Claude Files API 深入:从上传、复用到配额管理的工程化指南
android·java·数据库·人工智能·python·json·飞书
ujainu1 天前
CANN pto-isa:虚拟指令集如何连接编译与执行
android·ascend
赏金术士1 天前
第六章:UI组件与Material3主题
android·ui·kotlin·compose
TechMerger1 天前
Android 17 重磅重构!服役 20 年的 MessageQueue 迎来无锁改造,卡顿大幅优化!
android·性能优化
yuhuofei20211 天前
【Python入门】Python中字符串相关拓展
android·java·python
dalancon1 天前
Android Input Spy Window
android
dalancon2 天前
InputDispatcher派发事件,查找目标窗口
android
我命由我123452 天前
Android Framework P3 - MediaServer 进程、认识 ServiceManager 进程
android·c语言·开发语言·c++·visualstudio·visual studio·android runtime
天才少年曾牛2 天前
Android14 新增系统服务后,应用调用出现 “hidden api” 警告的原因与解决方案
android·frameworks