오늘 Android Studio 3.1로 업그레이드했는데 보푸라기 검사가 몇 개 더 추가 된 것 같습니다. 이러한 보푸라기 점검 중 하나 subscribe()
는 변수에 저장되지 않은 원샷 RxJava2 호출에 대한 것입니다. 예를 들어, 내 Room 데이터베이스에서 모든 플레이어 목록을 가져옵니다.
Single.just(db)
.subscribeOn(Schedulers.io())
.subscribe(db -> db.playerDao().getAll());
큰 노란색 블록과이 툴팁이 생성됩니다.
의 결과
subscribe
는 사용되지 않습니다
이와 같은 원샷 Rx 호출에 대한 모범 사례는 무엇입니까? Disposable
과 dispose()
를 계속 유지해야합니까 ? 아니면 그냥 계속해야 @SuppressLint
합니까?
이것은 RxJava2 ( io.reactivex
) 에만 영향을 미치는 것으로 보이며 RxJava ( rx
)에는이 보푸라기가 없습니다.
답변
IDE는 구독이 폐기되지 않을 때 구독에 미칠 수있는 영향을 알지 못하므로 잠재적으로 안전하지 않은 것으로 취급합니다. 예를 들어, Single
네트워크 호출이 포함되어있을 수 있습니다. 네트워크 호출 Activity
은 실행 중에 메모리가 누출 될 수 있습니다 .
많은 양의 Disposable
s 를 관리하는 편리한 방법 은 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을 정의 할 수 있으며 Observable 이 SubjectBehaviour (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> }