subscribe 결과는 사용되지 않습니다 저장되지 않은

오늘 Android Studio 3.1로 업그레이드했는데 보푸라기 검사가 몇 개 더 추가 된 것 같습니다. 이러한 보푸라기 점검 중 하나 subscribe()는 변수에 저장되지 않은 원샷 RxJava2 호출에 대한 것입니다. 예를 들어, 내 Room 데이터베이스에서 모든 플레이어 목록을 가져옵니다.

Single.just(db)
            .subscribeOn(Schedulers.io())
            .subscribe(db -> db.playerDao().getAll());

큰 노란색 블록과이 툴팁이 생성됩니다.

의 결과 subscribe는 사용되지 않습니다

Android Studio의 스크린 샷.  툴팁과 함께 코드가 노란색으로 강조 표시됩니다.  툴팁 텍스트 : 가입 결과가 사용되지 않습니다.

이와 같은 원샷 Rx 호출에 대한 모범 사례는 무엇입니까? Disposabledispose()를 계속 유지해야합니까 ? 아니면 그냥 계속해야 @SuppressLint합니까?

이것은 RxJava2 ( io.reactivex) 에만 영향을 미치는 것으로 보이며 RxJava ( rx)에는이 보푸라기가 없습니다.



답변

IDE는 구독이 폐기되지 않을 때 구독에 미칠 수있는 영향을 알지 못하므로 잠재적으로 안전하지 않은 것으로 취급합니다. 예를 들어, Single네트워크 호출이 포함되어있을 수 있습니다. 네트워크 호출 Activity은 실행 중에 메모리가 누출 될 수 있습니다 .

많은 양의 Disposables 를 관리하는 편리한 방법 은 CompositeDisposable 을 사용하는 것입니다 . 엔 CompositeDisposable클로징 클래스에서 새 인스턴스 변수를 만든 다음 모든 Disposables를 CompositeDisposable에 추가하십시오 (RxKotlin을 사용하면 addTo(compositeDisposable)모든 Disposables에 추가 할 수 있음 ). 마지막으로 인스턴스를 완료하면을 호출하십시오 compositeDisposable.dispose().

그러면 보푸라기 경고 Disposables가 사라지고 제대로 관리됩니다.

이 경우 코드는 다음과 같습니다.

CompositeDisposable compositeDisposable = new CompositeDisposable();

Disposable disposable = Single.just(db)
        .subscribeOn(Schedulers.io())
        .subscribe(db -> db.get(1)));

compositeDisposable.add(disposable); //IDE is satisfied that the Disposable is being managed. 
disposable.addTo(compositeDisposable); //Alternatively, use this RxKotlin extension function.


compositeDisposable.dispose(); //Placed wherever we'd like to dispose our Disposables (i.e. in onDestroy()).


답변

활동이 파괴되는 순간, 일회용품 목록이 지워지고 우리는 좋습니다.

io.reactivex.disposables.CompositeDisposable mDisposable;

    mDisposable = new CompositeDisposable();

    mDisposable.add(
            Single.just(db)
                    .subscribeOn(Schedulers.io())
                    .subscribe(db -> db.get(1)));

    mDisposable.dispose(); // dispose wherever is required


답변

DisposableSingleObserver 를 구독 할 수 있습니다 :

Single.just(db)
    .subscribeOn(Schedulers.io())
    .subscribe(new DisposableSingleObserver<Object>() {
            @Override
            public void onSuccess(Object obj) {
                // work with the resulting todos...
                dispose();
            }

            @Override
            public void onError(Throwable e) {
                // handle the error case...
                dispose();
            }});

Single객체 를 직접 처리해야하는 경우 (예 : 객체가 방출되기 전에) 참조 onSubscribe(Disposable d)를 가져 와서 사용하는 메소드 를 구현할 수 있습니다 Disposable.

당신은 또한 SingleObserver당신 자신의 인터페이스를 실현 하거나 다른 자식 클래스를 사용할 수 있습니다.


답변

제안했듯이 전역 CompositeDisposable작업을 사용하여 구독 작업 결과를 추가 할 수 있습니다 .

RxJava2Extensions의 라이브러리로부터 자동 생성 일회용 제거하는 유용한 방법을 포함 CompositeDisposable가 완료 될 때를. subscribeAutoDispose 섹션을 참조하십시오 .

귀하의 경우에는 다음과 같이 보일 수 있습니다

SingleConsumers.subscribeAutoDispose(
    Single.just(db)
            .subscribeOn(Schedulers.io()),
    composite,
    db -> db.playerDao().getAll())


답변

Uber AutoDispose 및 rxjava를 사용할 수 있습니다.as

        Single.just(db)
            .subscribeOn(Schedulers.io())
            .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
            .subscribe(db -> db.playerDao().getAll());

ScopeProvider를 기반으로 구독을 취소 할 때 이해해야합니다.


답변

나는 구독을 올바르게 처리하는 방법과 특히이 게시물에 대한 질문으로 다시 돌아 오는 것을 발견했습니다. 몇몇 블로그와 회담에서는 전화를하지 않으면 dispose반드시 메모리 누수가 발생한다고 주장합니다. 내 이해에 따르면, 결과를 저장하지 않는다는 보푸라기 경고는 subscribe다음과 같은 이유로 문제가 아닙니다.

  • 모든 관찰 가능 항목이 Android 활동의 컨텍스트에서 실행되는 것은 아닙니다.
  • 옵저버 블은 동기식 일 수 있습니다
  • 관찰이 완료되면 처리를 암시 적으로 호출합니다.

보푸라기 경고를 억제하고 싶지 않기 때문에 최근에 동기식 관찰 가능한 경우에 다음 패턴을 사용하기 시작했습니다.

var disposable: Disposable? = null

disposable = Observable
   .just(/* Whatever */)
   .anyOperator()
   .anyOtherOperator()
   .subscribe(
      { /* onSuccess */ },
      { /* onError */ },
      {
         // onComplete
         // Make lint happy. It's already disposed because the stream completed.
         disposable?.dispose()
      }
   )

정확성을 확인하거나 허점을 발견했는지 여부에 관계없이 이에 대한 의견에 관심이 있습니다.


답변

Disposables를 수동으로 사용하지 않는 다른 방법이 있습니다 (구독 추가 및 제거).

Observable을 정의 할 수 있으며 ObservableSubjectBehaviour (RxJava를 사용하는 경우) 에서 컨텐츠를 수신하게됩니다 . 그리고 관찰 가능한 것을 LiveData 에 전달 하면 작동합니다. 초기 질문을 바탕으로 다음 예를 확인하십시오.

private val playerSubject: Subject<Player> = BehaviorSubject.create()

private fun getPlayer(idPlayer: String) {
        playerSubject.onNext(idPlayer)
}

private val playerSuccessful: Observable<DataResult<Player>> = playerSubject
                        .flatMap { playerId ->
                            playerRepository.getPlayer(playerId).toObservable()
                        }
                        .share()

val playerFound: LiveData<Player>
    get() = playerSuccessful
        .filterAndMapDataSuccess()
        .toLiveData()

val playerNotFound: LiveData<Unit>
    get() = playerSuccessful.filterAndMapDataFailure()
        .map { Unit }
        .toLiveData()

// These are a couple of helpful extensions

fun <T> Observable<DataResult<T>>.filterAndMapDataSuccess(): Observable<T> =
filter { it is DataResult.Success }.map { (it as DataResult.Success).data }

fun <T> Observable<DataResult<T>>.filterAndMapDataFailure(): Observable<DataResult.Failure<T>> =
filter { it is DataResult.Failure }.map { it as DataResult.Failure<T> }