이전 포스트들에서 Observable 객체에서 발행할 아이템을 정의한 후 subscribe()를 통해 스트림을 생성하고 아이템을 발행했습니다. 이 subscribe()를 호출한 후에는 Disposable 객체가 반환됩니다.
코드
fun main() {
val observer : Observable<String> = Observable.just("heetae","Velog",RxJava")
val disposable : Disposable = observer.subscribe(System.out::println)
}
Observable이 발행하는 아이템의 개수가 정해져 있다면 모두 발행된 이후 onComplete()가 호출되고 안전하게 종료될 것입니다. 하지만 아이템이 무한정 데이터를 발행하거나 오랫동안 데이터를 발행하는 Observable의 경우에는 onComplete()가 호출되지 않거난 호출되기까지 오래 걸립니다.
따라서 이들을 제대로 종료하지 않으면, 메모리 릭이 발생하게 되는 것입니다.
더 이상 Observable의 구독이 필요하지 않을 때에는 이를 dispose해주어 메모리 효율을 가져갈 수 있습니다.
fun main() {
val stream: Observable<Long> = Observable.interval(1, TimeUnit.SECONDS)
val disposable: Disposable = stream.subscribe(System.out::println)
Thread.sleep(4000)
disposable.dispose()
}
다음을 출력하게 된다면 결과는 다음과 같습니다.
0
1
2
3
4초 후에 Observable 데이터 발행이 중단되고 모든 리소스가 폐기됩니다. Disposable.isDisposed()를 통해 리소스 폐기 여부를 체크할 수 있습니다.
만약 구독자가 여러 곳에 있다면 이들을 폐기하려면 Observable마다 Disposable을 호출하여 종료시켜주어야 합니다.
하지만 compositeDisposable을 사용한다면 일괄적으로 해제가 가능한데 방법은 2가지가 있습니다. 바로 clear()와 dispose() 입니다.
두가지 차이점은 dispose()는 isDisposed를 true값으로 변경하는데 이 때문에 dispose() 이후에 add 함수 내부적으로 isDisposed가 true일때 이런하게 되어있습니다.
반대로 clear()는 Disposable들을 해제 후에 다시 add가 가능합니다.
fun main() {
val stream : Observable<Long> = Observable.interval(1,TimeUnit.SECONDS)
val disposableA: Disposable = stream.subscribe(System.out::println)
val disposableB: Disposable = stream.subscribe(System.out::println)
val disposableC: Disposable = stream.subscribe(System.out.println)
val disposableD: Disposable = stream.subscribe(System.out.println)
val compositeDisposable = CompositeDisposable()
compositeDisposable.add(disposableA)
compositeDisposable.add(disposableB)
compositeDisposable.add(disposableC)
compositeDisposable.add(disposableD)
Thread.sleep(3000)
compositeDisposable.dispose()
}
결과는 다음과 같습니다.
0
0
0
0
1
1
1
1
2
2
2
2
만약 안드로이드에서 Retrofit을 이용해 여러 통신 작업을 수행한 후 이를 한꺼번에 dispose하기 위해서 CompositeDispoable을 사용하기도 합니다. 안드로이드 라이프사이클에 맞춰 동작시키려고 한다면 compositeDisposable.dispose()를 onDestroy()에서 호출하여 모든 자원을 폐기할 수 있습니다.
각 컴포넌트의 라이프사이클에 맞게 해재해 주어야 메모리 누수에 안전하기에 대표적인 컴포넌트들은(Activty, Fragment, ViewModel의 각 해제 시점은 onDestroy, onDestroyView, clear 입니다.
http://reactivex.io/documentation/operators
https://velog.io/@haero_kim/RxJava-Disposable-%EB%8B%A4%EB%A4%84%EB%B3%B4%EA%B8%B0
https://blog.yena.io/studynote/2020/12/06/Android-RxJava(4).html
https://medium.com/kenneth-android/rxjava-compositedisposable%EC%9D%98-clear-%EC%99%80-dispose-%EC%9D%98-%EC%B0%A8%EC%9D%B4-86e19796e5b0