Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RxJava+改造共享()运算符_Android_Rx Java_Retrofit_Retrofit2_Rx Java2 - Fatal编程技术网

Android RxJava+改造共享()运算符

Android RxJava+改造共享()运算符,android,rx-java,retrofit,retrofit2,rx-java2,Android,Rx Java,Retrofit,Retrofit2,Rx Java2,这里的特殊rx场景: 改装空气污染指数: interface MyApi { @Headers("Content-Type: application/json") @POST("something") fun doSomething(@Body body: SomeRequestBody): Single<SomeResponse> } 我的理解是,如果所有订阅都已被处理,共享的observable将从其源中处理掉。当test2调用doSomething时,将发生另一个

这里的特殊rx场景:

改装空气污染指数:

interface MyApi {
  @Headers("Content-Type: application/json")
  @POST("something")
  fun doSomething(@Body body: SomeRequestBody): Single<SomeResponse>
}
我的理解是,如果所有订阅都已被处理,共享的observable将从其源中处理掉。当test2调用doSomething时,将发生另一个API调用。第二次测试未能反映这一点

另一件事,如果我将API调用包装为defer,则两个测试都会通过:

private val observable: Observable<SomeResponse> by lazy {
  Single.defer {
    myApi.doSomething(SomeRequestBody())
  }.toObservable().share()
}

希望有人能对此做出解释。

正如评论中所讨论的,问题是可观察的初始化。这里有更详细的解释

问题在于:

private val observable: Observable<SomeResponse> by lazy {
  myApi.doSomething(SomeRequestBody())
    .toObservable()
    .share()
}
变量observable是延迟初始化的,这意味着只要我们使用存储库的同一个实例,它就只能初始化一次

因此,在测试中,您有一个存储库实例和几个测试。这意味着,对于整个测试类,惰性块中的代码只运行一次。也就是说,myApi.doSomethingany只运行一次。当您尝试验证多个交互时,这会导致失败

当你把它包装在一个defer中时,它起作用的原因是defer创建了一个observable,它将在每次订阅者订阅时执行。在你的例子中,由于share操作符,它有点复杂,但想法是一样的。与之前一样,延迟执行是惰性的,在测试期间不会再次调用。也就是说,如果一个人可以验证延迟调用,那么结果将是相同的。但是,现在每次运行observable时,它都会调用myApi.doSomethingany,测试就会通过


正如您已经发现的,您可以通过将呼叫包装为延迟来解决此问题。我认为您也可以简单地删除延迟初始化。也许,甚至可以使用依赖项注入在测试中不延迟地初始化对象,但在生产应用程序中保持它的延迟初始化。

我可能没有正确地理解这一点,但这不是因为您正在延迟初始化存储库内部可观察的吗?它初始化一次并调用doSomething方法,但当repo的实例保持不变时,它将不再调用它。将其包装在defer中,使其成为订阅后执行的可观察对象的一部分,但defer本身只被调用一次。订阅时,不会进行任何新的延迟调用,但它将再次运行执行doSomething行的源代码,并且测试通过。这可以理解吗?“如果你去掉懒惰的部分,效果会好吗?”弗雷德,我想正是这样。我还注意到,在没有Signle.defer/fromCallable的情况下,使用MockWebServer进行测试而不是像上面那样模拟API也是可行的。所以,可能是Rx呼叫适配器也在做类似的事情。如果不麻烦的话,你能把这个作为一个答案吗?谢谢:当然!很高兴,我稍后会在我的笔记本电脑上做:很高兴它能工作。
private val observable: Observable<SomeResponse> by lazy {
  Single.defer {
    myApi.doSomething(SomeRequestBody())
  }.toObservable().share()
}
private val observable: Observable<SomeResponse> by lazy {
  myApi.doSomething(SomeRequestBody())
    .toObservable()
    .share()
}