Lint 기능이 강화되면서 Handler 쪽에서 발생 안 하던 lint(warning) 가 발생하더군요.
handler should be static, else it is prone to memory leaks
바로 요런 해괴한 녀석.
이 녀석이 나오는 원인은 Handler 와 Looper, MessageQueue의 관계.. 그리고 reference 의 관계를 잘 생각해봐야 합니다.
<생각하기>
- Main Thread ( or UI Thread ) 에서 Handler 를 만들게 되면, 해당 Thread 와 연결이 되는 것은 물론, 해당 Activity 혹은 Context 를 참조까지 하게 됩니다.
- MessageQueue 에 있는 Message 는 Target Handler 를 reference 하고 있습니다. 그래서, Activity 가 종료되어도 MessageQueue에 해당 Handler 에 대한 Message 가 쌓여 있는 경우 Handler 는 GC 되지 않습니다. ( 모든 handler 관련 메세지가 소비되면 GC 가 되기는 하겠죠..? 하지만 최악의 상황에는.. 음.. )
- Handler 가 GC 되지 않으면, Handler 가 참조하는 Activity 도 GC 가 되지 않고 결국 Memory Leak 이 나게 됩니다.
그럼 어떻게 해결해야 하느냐? 다음과 같이 하면 됩니다.
<WeakRefHandler.java>
public class WeakRefHandler extends Handler{
private final WeakReference<IOnHandlerMessage> mHandlerActivity;
public WeakRefHandler(IOnHandlerMessage activity) {
mHandlerActivity = new WeakReference<IOnHandlerMessage>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
IOnHandlerMessage activity = (IOnHandlerMessage) mHandlerActivity.get();
if ( activity == null ) return;
activity.handleMessage(msg);
}
}
<IOnHandlerMessage>
public interface IOnHandlerMessage {
public void handleMessage( Message msg );
}
<사용코드>
class TestActivity extends Activity implements IOnHandlerMessage{
..
WeakRefHandler handler = new WeakRefHandler( this );
..
}
위와 같이 WeakReference 를 사용하면, Activity 에 대한 직접적인 참조가 일어나지 않기 때문에 Message Queue 에 해당 handler 관련된 message 가 쌓여있어도, Activity 는 GC 가 일어날 수 있다.
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[android/안드로이드] Handler 의 내부적 진실. (4) | 2012.10.05 |
---|---|
[android/안드로이드] Dialog positive button, neutral button, negative button 위치 (0) | 2012.10.05 |
[android/안드로이드] strings.xml 에서 다른 string resource 참조하기. (0) | 2012.10.05 |
[android/안드로이드] android repository address (0) | 2012.10.04 |
[android/안드로이드] layout xml의 tools:context 은 뭔가요? (8) | 2012.10.04 |
댓글