2016-08-04 4 views
0

첫 번째는 Android가 처음이지만 iOS 세계에서 RxSwift를 광범위하게 사용하여 매우 이상하게 느껴지는 동작을 발견했습니다.Android RxJava onNext는 Observer가 구독 취소 된 경우에도 호출됩니다.

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하지이 그 관찰자가이 마지막 호출이 수신을 거부하다 볼 수있는 경우를

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 

될 나타나지 않습니다 탈퇴 때 호출되는 및 (여기서 볼 수는 없지만 pari 대신 par 결과가 있기 때문에 발생합니다) doOnNext 클로저는 구독 취소 된 경우에도 내 관찰 가능 항목에서 실행됩니다.

나는 인터넷을 파고 들어갔다. cache을 전혀 사용하지 않는다는 것을 제외하면 동일한 문제를 설명하는 것으로 보이는 this을 발견했다.

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

을하고, 객체는 텍스트 뷰 업데이트

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

관련 문제