본문 바로가기

Language/RxJava

[RxJava] 6장. 안드로이드의 RxJava 활용 4 - 메모리 누수

728x90

메모리 누수

메모리 누수(Memory Leak)란 보통 참조가 완료되었지만 할당한 메모리를 해제하지 않았을 때 발생.

특히, 강한 참조의 경우 가비지 컬렉터가 메모리에서 객체를 제거할 수 없으므로 라이프 사이클에 맞게 객체 참조를 끊어주어야 메모리 해제가 가능하다.

메모리 누수는 시스템 전체 성능에 영향을 미친다.

 

*

Observable은 안드로이드의 컨텍스트(Context)를 복사하여 유지한다.

onComplete(), onError() 함수가 호출되면 내부에서 자동으로 unsubscribe() 함수를 호출하여 메모리를 해제해준다.

 

하지만, 액티비티가 비정상적으로 종료되면 액티비티가 종료되어도 가비지 컬렉션의 대상이 되지 못하는 경우가 발생할 수 있으며, 이 때 메모리 누수가 발생하게 된다.

 

메모리 누수 해결방안

Disposable 인터페이스를 이용한 명시적 자원 해제

  • onCreate() 에서 subscribe()를 호출하면 onDestory() 에서 메모리 참조를 해제.
  • onResume()에서 subscribe()를 호출하면 onPause() 에서 메모리 참조를 해제.

RxLifecycle 라이브러리 이용

액티비티의 부모를 RxAppCompatActivity로 변경하고 compose() 함수를 사용하여 RxLifecycle 라이브러리를 적용.

 

public class SampleRxLifecycle extends RxAppCompatActivity {

	prvate Unbinder mUnbinder;
	...
    

	Observable.create(~)
		//.compose(bindToLifecycle())
		.compose(bindUntilEvent(ActivityEvent.DESTROY))
		.subscribe(~);

	...
    
    
	@Override
	public void onDestroy() {
		super.onDestroy();

		if (mUnbinder != null) {
			mUnbinder.unbind();
		}
    
	}
    
	...
    
}

 

compose(bindToLifecycle()) 함수를 사용하게 되면, onCreate - onDestroy, onResume - onPause 메서드가 쌍으로 동작한다. 즉, onCreate에서 subscribe를 호출하면 onDestroy에서 unsubscribe를 호출한다.

 

bindUntilEvent 함수를 선언하면 종료되는 시점을 직접 설정할 수 있다.

ActivityEvent를 활용해 종료되는 시점을 선택할 수 있다.

 

public enum ActivityEvent {
	CREATE,
	START,
	RESUME,
	PAUSE,
	STOP,
	DESTROY
}

 

CompositeDisposable 클래스 이용

CompositeDisposable 클래스를 이용하면 생성된 모든 Observable을 안드로이드 라이프 사이클에 맞춰 한번에 모두 해제할 수 있다.

 

사용하는 방법은, 첫 번째 해결책의 연장선이다.

첫 번째 해결책은 DisposableObserver 객체를 직접 해지하는 반면,

이 방법은 Publisher.subscribe() 를 이용하여 Disposable을 리턴한 후 CompositeDisposable 클래스에서 일괄적으로 처리하는 방식이다.

 

Publisher.subscribe()는 return 값이 void 이므로, subscribeWith() 함수를 사용하거나 인자에 소비자(Consumer)를 전달해 Disposable 객체를 리턴받아야 한다.

728x90