This Handler class should be static or leaks might occur

원글 : http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

[code lang=”js”]
public class SampleActivity extends Activity
{
private final Handler mLeakyHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// …
}
}
}
[/code]

In Android, Handler classes should be static or leaks might occur.

이것이 나오는 원인은

1. Android Application이 실행될 때, Framework에서는 Application의 메인 쓰레드를 위한 Loop Object를 생성 한다. Looper는 단순한 메시지 큐를 생성하여 Message들을 처리하고, Application의 Lifecycle과 동일한 Lifecycle을 갖는다.
2. 메인 쓰레드에서 생성된 Handler는 Looper의 메시지 큐에 속하게 된다. 메시지 큐로 보내진 Message들은 Handler에 대한 reference를 갖고 있어야함, Looper가 해당 메시지를 처리 할수 있다. Looper가 메시지를 처리할 때 Handler#handleMessage(Message)를 호출해야 하기 때문.
3. Java에서는 non-static inner class와 anonymous class는 outer class에 대한 implicit reference를 갖고, static inner class의 경우에는 갖지 않는다. 

Handler와 Looper, Message Queue의 관게을 해결하기 위해 위 문제를 해결하기 위해서는 Handler를 static inner class로 정의하거나, 새로운 파일에 subclass해야 한다. static inner class는 outer class에 대한 implicit reference를 갖기 않기 때문에 Activity Context가 Garbage Collect되는 것을 방해하지 않을 것이다. 만약 Handler 내부에서 Activity의 method를 호출해야 할 경우 Activity의 WeakReference를 갖도록 한다.

[code lang=”js”]
public class SampleActivity extends Activity
{

/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class MyHandler extends Handler
{
private final WeakReference<SampleActivity> mActivity;

public MyHandler( SampleActivity activity )
{
mActivity = new WeakReference<SampleActivity>( activity );
}

@Override
public void handleMessage( Message msg )
{
SampleActivity activity = mActivity.get();
if( activity != null )
{
// …
}
}
}

private final MyHandler mHandler = new MyHandler( this );

/**
* Instances of anonymous classes do not hold an implicit
* reference to their outer class when they are "static".
*/
private static final Runnable sRunnable = new Runnable()
{
@Override
public void run()
{
}
};

@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );

// Post a message and delay its execution for 10 minutes.
mHandler.postDelayed( sRunnable, 600000 );

// Go back to the previous Activity.
finish();
}
}
[/code]

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다