read
출처 : How to Leak a Context: Handlers & Inner Classes
안드로이드에서 Handler 를 non-static anonymous 클래스로 만들면 위와 같은 경고 문구를 만날 수 있다. 메세지 내용은 메모리 릭이 날 수 있다는 이야기인데. 무슨 릭이 날까 검색해보니 그럴수도 있을 만한 이야기다. 우선 아래의 코드를 한 번 보자.(자세한 사항은 출처 참고)
public class SampleActivity extends Activity {
private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
/* ... */
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Post a message and delay its execution for 10 minutes.
mLeakyHandler.postDelayed(new Runnable() {
public void run() { }
}, 600000);
// Go back to the previous Activity.
finish();
}
}
이 코드는 10 분 후에 핸들러로 메세지를 보내게 하고, 액티비티를 바로 종료시키는 코드다. 여기서 발생하는 메모리릭이란 10분 동안 SampleActivity 가 garbage collecting 되지 않는 것을 말한다. 그 이유는 다음과 같다.
- 안드로이드 애플리케이션에는 Looper 라는 객체가 있다. 이 객체는 Application 과 lifecycle 을 같이함.
- Handler 인스턴스가 생기면, Looper 의 메세지큐와 엮이게 됨.
- 자바에서 non static inner class 와 anonymous class 는 outer class 에 대한 레퍼런스를 몰래 가지고 있음.
이거 때문에 위의 예제 코드에서 finish(); 가 콜이 된 후의 상황은 다음과 같다.
- 메세지 큐에 10 분 뒤 실행될 메세지가 들어 있음
- 이 메세지는 핸들러에 대한 레퍼런스를 가지고 있음
- 핸들러는 outer class 인 SampleActivity 에 대한 레퍼런스를 가지고 있음
- finish() 가 되어 액티비티 객체는 종료되었지만, 레퍼런스가 존재하기 때문에 garbage collecting 되지 않음.
이를 해결하는 방법은 핸들러 클래스를 static inner class 로 선언하던가 아니면 별도의 클래스 파일로 분리시키던가 해야 되고, Activity 의 메소드에 접근하고 싶다면 weakreference 등을 활용해야 한다는 거.