单个,发出传递函数返回的值

时间:2017-11-06 21:58:11

标签: java android rx-java

我想要一个调用某个函数的Single,然后用函数返回的值完成。

以下是类似的内容:

Single.fromCallable(this::func);

问题在于每次添加订阅者时都会调用:: func。因此,如果这个:: func计算单个将返回3到第三个订阅者的调用。
我认为这是一个问题,因为,如果这个:: func是一个长时间运行的操作。
我不明白,这是否意味着Single :: onComplete被调用了两次?我认为这是不可能的,而且没有意义,因为,有什么东西可以完成两次?

既然我是Android程序员Single :: fromFuture在这里不起作用,还有其他选择吗?

我将通过以下示例演示我的问题:

class SingleFromCallableTest {

    int funcCalls = 0;

    int func(){
        return funcCalls++;
    }

    @Test
    public void run(){
        Single<Integer> source = Single.fromCallable(this::func);
        source.subscribe(System.out::println);  // prints 1
        source.subscribe(System.out::println);  // prints 2
    }
}

IMO,第二个订阅者不应该被调用,因为Single应该只在IMO成功一次。 就像SingleSubject一样,一旦你调用onSuccess,它就无法再次成功。

如果Single.fromCallable按照它认为应该的方式工作,那么在前一个例子中,source甚至可以在第一个订阅者订阅之前完成,这意味着,只有以下订阅方式会有意义的:

Single.fromCallable(this::func).subscribe(System.out.println);

但实际上,即便如此,也许有可能不会捕捉到单身的价值,也许这是不可能的。

1 个答案:

答案 0 :(得分:2)

方法#fromCallable是一个工厂,每次都会返回一个新的Single。在每次订阅时,您将订阅一个新的单身。因此,将为每个订户调用该函数。如果要缓存该值,则应使用#cache运算符。请看看提供的两个测试。

测试&#39; notCached&#39;将为每个订阅调用该函数。测试&#39;缓存&#39;只会调用一次该函数。如果要共享结果,只需使用#cache运算符重新使用create Single#fromCallable。

环境

dependencies {
compile 'io.reactivex.rxjava2:rxjava:2.1.6'
compile 'org.mockito:mockito-core:2.11.0'
testCompile("org.junit.jupiter:junit-jupiter-api:5.0.0")
testRuntime("org.junit.jupiter:junit-jupiter-engine:5.0.0")

测试

@Test
void notCached() throws Exception {
    Callable<Integer> mock = mock(Callable.class);

    when(mock.call()).thenReturn(10);

    Single<Integer> integerSingle = Single.fromCallable(mock);

    Disposable subscribe1 = integerSingle.subscribe();
    Disposable subscribe2 = integerSingle.subscribe();

    verify(mock, times(2)).call();
}

@Test
void cached() throws Exception {
    Callable<Integer> mock = mock(Callable.class);

    when(mock.call()).thenReturn(10);

    Single<Integer> integerSingle = Single.fromCallable(mock).cache();

    Disposable subscribe1 = integerSingle.subscribe();
    Disposable subscribe2 = integerSingle.subscribe();
    Disposable subscribe3 = integerSingle.subscribe();
    Disposable subscribe4 = integerSingle.subscribe();

    verify(mock, times(1)).call();
}