Android RxJava onNext甚至在观察者取消订阅时调用

时间:2016-08-04 10:18:36

标签: android rx-java kotlin

我是Android新手,但是从iOS世界开始,我广泛使用RxSwift并发现了一种我觉得非常奇怪的行为。

我将一个改装调用封装到一个RxJava Observable(我没有使用RxJavaCallAdapterFactory,但我真的认为这不是问题。)

fun SearchService.rx_myObjects(query: String?): Observable<List<MyClass>> {
    return Observable.create { observer ->
        val request = getMyObjects(query = query)
        request.enqueue(object : Callback<MyClass>() {
            override fun onSuccess(result: MyClass) {
                Log.v("TEST", "is unsubscribed ${observer.isUnsubscribed} for query $query")
                observer.onNext(result)
                observer.onCompleted()
            }

            override fun onError(error: APIError) {
                observer.onError(error)
            }
        })
    }
}

虽然我怀疑在取消订阅该观察者时要调用onNext NOT ,但似乎并非如此

08-04 11:50:39.767 5107-5107/com.mydomain.myapp V/TEST: is unsubscribed false for query par
08-04 11:50:44.264 5107-5107/com.mydomain.myapp V/TEST: is unsubscribed true for query pari
08-04 11:50:44.653 5107-5107/com.mydomain.myapp V/TEST: is unsubscribed false for query par
08-04 11:50:46.358 5107-5107/com.mydomain.myapp V/TEST: is unsubscribed false for query pari
08-04 11:50:47.990 5107-5107/com.mydomain.myapp V/TEST: is unsubscribed false for query pari
08-04 11:50:48.033 5107-5107/com.mydomain.myapp V/TEST: is unsubscribed true for query par

你可以看到最后一个电话是取消订阅的(你在这里看不到但是它发生了,因为我有par个结果而不是pari个结果doOnNext即使取消订阅,我的观察也会执行封闭。

我已经深入互联网并发现this似乎描述了同样的问题,除了我根本没有使用cache

这是我的订阅电话:

private fun retrieveMyObjects(query: String?) {
        subscription = service.rx_myObjects(query = query)
            .doOnError { showError(it) }
            .doOnNext { this.airports = it }
            .subscribe()
    }

并在textView更新

上触发对象调用
search_view.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
    override fun onQueryTextChange(newText: String?): Boolean {
        subscription?.unsubscribe()
        retrieveMyObjects(newText)

        return true
    }
})

有什么建议吗?我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:1)

在最坏的情况下:您执行http呼叫。然后,如果文本更改,您取消订阅以前的订阅,然后执行另一个http调用。但是,第一个http调用的响应只会产生。

这就是你有这种日志订单的原因。由于你有Observable的取消订阅,它不应该发出新值。为此,您可以在if / onNext块之前添加简单的oncompleted

request.enqueue(object : Callback<MyClass>() {
        override fun onSuccess(result: MyClass) {

            if(!observer.isUnsubscribed()) {
                  Log.v("TEST", "is unsubscribed ${observer.isUnsubscribed} for query $query")
                  observer.onNext(result)
                  observer.onCompleted()
             }
        }

        override fun onError(error: APIError) {
            if(!observer.isUnsubscribed()) {
                  observer.onError(error)
            }
        }
    })

像这样,你可以避免发出一个不会被后续处理的值(当你取消订阅时)

请注意,您正在使用Observable.create:您可能会因为必须管理很多事情而避免使用它,例如Rx合同,取消订阅,背压。因此,您可以按照建议使用RxJavaCallAdapterFactory,或尝试Observable.fromAsync