Posts [RxJava2] Disposable - 메모리 누수를 막아보자
Post
Cancel

[RxJava2] Disposable - 메모리 누수를 막아보자

Disposable

RxJava1에서 사용되던 Subscription이 RxJava2에서 Disposable로 바뀌었습니다.

옵저버블을 통해 데이터 스트림을 발행하고 subscribe() 함수들을 사용하여 구독할 때에 이 함수가 반환하는 값이 Disposable 인터페이스의 객체 입니다.

Disposable의 dispose() 함수를 통해 옵저버블에게 더이상 데이터를 발행하지 않도록 할 수 있습니다.

즉, 이를 통해 옵저버블을 사용함으로서 발생할 수 있는 메모리 누수를 막을 수 있습니다.

dispose()
  • 옵저버블에게 더이상 데이터를 발행하지 않도록 구독을 해지하는 함수입니다.
  • 옵저버블이 onComplete() 알림을 보냈을 때 자동으로 dispose()를 호출해 옵저버블과 구독자의 관계를 끊게 됩니다.
clear()
  • add된 옵저버블을 해지합니다.
  • 단, isDisposed()가 false이기 때문에 재사용이 가능합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// BoardFragment 파괴되는 시점에 Disposable을 통해 리소스 해제
override fun onDestroy() {
    super.onDestroy()

    viewModel.run {
        clearCompositeDisposable()
    }
}

//
abstract class BaseViewModel : ViewModel() {
    protected val compositeDisposable = CompositeDisposable()

    /**
     * 쌓인 compositDisposable을 clear
     *
     * Activity/Fragment의 onDestroy 타이밍에 리소스 정리
     * dispose() 호출 시 compositeDisposable 재사용이 불가능하므로 clear()만 수행
     */
    fun clearCompositeDisposable() {
        compositeDisposable.clear()
    }

    /**
     * ViewModel이 제거될 때 호출되는 onCleared()
     *
     * compositeDisposable을 재사용할 일이 없으므로 dispose() 수행
     */
    override fun onCleared() {
        super.onCleared()
        compositeDisposable.dispose()
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 게시글 목록 요청 API 예시
compositeDisposable.add(
    repository.getAllBoardList()
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeWith(object : DisposableObserver<List<Board>>() {
            override fun onComplete() {
                // do nothing.
                Log.d(TAG, "onComplete() called.")
            }

            override fun onNext(boards: List<Board>) {
                boardList.postValue(boards)
            }

            override fun onError(e: Throwable) {
                Log.w(TAG, "onError() | ", e)
            }
        })
)

옵저버블의 subscribe의 반환값은 Disposable 이기 때문에 전역으로 선언해둔 compositeDisposable에 add를 통해 disposable을 하나의 객체로 모아줍니다.

해당 ViewModel을 포함하고 있는 View(BoardFragment)가 onDestroy() 될 때 compositDisposable.clear()를 호출해 리소스를 해제시키고, ViewModel이 onCleared() 될 때 compositDisposable.dispose()를 호출해 add 된 옵저버블들에 대한 리소스를 모두 해제시켜줍니다.

이와 같이 사용할 경우 Activity나 Fragment가 비정상적으로 종료되었을 경우 혹은 옵저버블의 onComplete()onError() 를 타지 않는 경우에도 메모리 누수에 대한 방어가 가능합니다.




참고 사이트
This post is licensed under CC BY 4.0 by the author.

[RxJava2] Observable 가공은 어떻게 하는걸까?

[DI] 의존성 주입? Dagger?

Comments powered by Disqus.