2016-08-04 6 views
0

最初はAndroidには新しいですが、iOSの世界からはRxSwiftを広範囲に使用し、非常に奇妙な動作を見つけました。Android RxJava onNextはオブザーバーが登録解除されているときでも呼び出されます

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

そして、私はその観察者が解除されたときに、これはあなたが最後の呼び出しを見ることができるように、ケース

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 

ではないように呼ばれるonNextませが解除され疑いながら(ここでは見ることはできませんが、pariの代わりにparの結果があるために起こっています)、doOnNextクロージャが登録解除されていても私の観測で実行されます。

私はインターネットを掘り下げ、を全く使用していないこと以外は同じ問題を説明していると思われるthisを見つけました。ここで

は私のサブスクリプションの呼び出しです:

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

最悪の場合:httpコールを実行します。その後、テキストが変更された場合は、前のサブスクリプションから退会し、別のhttpコールを実行します。しかし、最初のhttp呼び出しからの応答はちょうど起動します。

このようなログ注文があるのはこのためです。 Observableから退会しているので、新しい価値を出すべきではありません。このためには、onNext/oncompletedブロックの前に簡単なifを追加することができます(あなたがそれから退会など)このよう

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に試してみてください。

+0

@dwursteisenに感謝します。これはまさに私が思ったものですが、RxSwiftにはまったく問題はありませんでした。 'AnonymousDisposable'を使用してリクエストを取り消すことができるので、少し違って動作します。 – apouche

関連する問題