개발/안드로이드

RxJava dispose()

kwony 2021. 9. 16. 20:00

이번 포스트에서는 RxJava를 사용할때 왜 dispose() 함수를 호출해서 메모리 정리를 해야하는지를 사례를 통해서 정리해보고자 한다.

 

class LeakActivity : AppCompatActivity() {
    private var disposable1 : Disposable? = null

    companion object {
        private const val TAG: String = "leak_activity_tag"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val observeSource = Observable.interval(1, TimeUnit.SECONDS)
        disposable1 = observeSource.subscribe { Log.d(TAG, "subscriber1 value: $it") }
        observeSource.subscribe { Log.d(TAG, "subscriber2 value: $it") }
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroyCalled")
        disposable1?.dispose()
        disposable1 = null
    }
}

 

이 액티비티는 생성하면서 1초 마다 이벤트를 보내는 Observable을 생성하고 두개의 subscriber로 구독하고 있다. 그리고 종료될 때는 첫번째 subscriber만 구독 모델을 해지한다. Activity를 종료하기 전까지는 두 subscriber에서 동시에 로그가 출력되는데

 

2021-09-16 17:48:01.106 subscriber2 value: 0
2021-09-16 17:48:01.106 subscriber1 value: 0
2021-09-16 17:48:02.106 subscriber1 value: 1
2021-09-16 17:48:02.107 subscriber2 value: 1
2021-09-16 17:48:03.106 subscriber2 value: 2
2021-09-16 17:48:03.106 subscriber1 value: 2
2021-09-16 17:48:04.106 subscriber1 value: 3
2021-09-16 17:48:04.106 subscriber2 value: 3

 

액티비티를 종료하고 나면 subscriber2에서 계속 로그가 출력된다. 화면이 없어졌는데도 이벤트를 지속적으로 구독하고 있다.

 

2021-09-16 17:48:44.907 onDestroyCalled
2021-09-16 17:48:45.106 subscriber2 value: 44
2021-09-16 17:48:46.107 subscriber2 value: 45
2021-09-16 17:48:47.106 subscriber2 value: 46

 

심각한 것은 백버튼으로 앱을 종료한 후 다시 실행해도 계속 구독하고 있게 된다는 것이다.  아래 로그를 보면 subscriber2 로그가 두번씩 찍히는데 이것은 이전에 남아있는 액티비티에서 구독한 subscriber가 계속 출력되기 때문이다.

 

2021-09-16 17:50:58.964 subscriber2 value: 0
2021-09-16 17:50:58.964 subscriber1 value: 0
2021-09-16 17:50:59.106 subscriber2 value: 178
2021-09-16 17:50:59.964 subscriber1 value: 1
2021-09-16 17:50:59.965 subscriber2 value: 1
2021-09-16 17:51:00.106 subscriber2 value: 179
2021-09-16 17:51:00.963 subscriber1 value: 2
2021-09-16 17:51:00.963 subscriber2 value: 2
2021-09-16 17:51:01.106 subscriber2 value: 180
2021-09-16 17:51:01.963 subscriber2 value: 3
2021-09-16 17:51:01.963 subscriber1 value: 3
2021-09-16 17:51:02.106 subscriber2 value: 181

 

단발성 이벤트를 구독했다면 큰 문제는 되지 않는다 하지만 위 코드처럼 지속적으로 이벤트를 보낸다면 그리고 subscriber 내부에서 메모리 할당 작업이 포함돼있었다면 메모리 릭이 발생하게 된다.