代码之家  ›  专栏  ›  技术社区  ›  Scarass

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

  •  0
  • Scarass  · 技术社区  · 7 年前

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

    以下是类似的情况:

    Single.fromCallable(this::func);
    


    我认为这是一个问题,因为,如果::func是一个长时间运行的操作怎么办。
    我不明白,这是否意味着Single::onComplete被调用了两次?我认为这是不可能的,这没有意义,因为,一件事怎么能完成两次?

    既然我是一个Android程序员单身汉::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。

    如果 Single.fromCallable source 甚至在第一个订阅者订阅之前就可以完成,这意味着,只有以下订阅方式才有意义:

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

    但实际上,即使这样,也有可能捕捉不到单粒子发射的值,也许这是不可能的。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Sergej Isbrecht    7 年前

    方法#fromCallable是一个工厂,每次都会返回一个新的。每次订阅你都会订阅一首新的单曲。因此,将为每个订阅者调用该函数。如果要缓存该值,可以使用#cache运算符。请看提供的两个测试。

    测试“notCached”将为每个订阅调用该函数。测试“缓存”将只调用函数一次。如果您想共享结果,只需使用create Single#fromCallable with#cache操作符。

    环境

    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();
    }