반응형
안드로이드(Android) This Handler class should be static or leaks might occur 해결 |
환경 : Eclipse Mars, Android 4.2.2 |
안드로이드에서 Handler 오브젝트는 모든 스레드 반복문에서 참조하는데 어느 한곳에 종속되면 안되기 때문입니다. 그렇게 되면 가비지 컬렉션이 되지 않아 메모리릭이 계속해서 발생하게 되는 것이죠.
▼ 아래 그림은 This Handler class should be static or leaks might occur 경고가 나 있는 소스를 캡쳐한 것입니다.
▼ 이것을 해결하기 위해 Handler 를 상속받은 클래스를 하나 만들어 static 등록해 놔야 합니다. 아래 소스는 이전 소스이며 이것을 고쳐보도록 하겠습니다.
handler = new Handler() { @Override public void handleMessage(Message msg) { // super.handleMessage(msg); if (myTextOn) { myTextOn = false; myText.setVisibility(View.GONE); } else { myTextOn = true; myText.setVisibility(View.VISIBLE); } } };
▼ Static 클래스를 하나 만듭니다. 그리고 handleMessage() 함수를 오버라이드 해서 메인 activity 에 미리 만들어 놓은 handleMessage() 호출해 줍니다. 호출할때 스레드에서 전달받은 메시지를 메인으로 보내면 되겠죠
private final MyHandler mHandler = new MyHandler(this); // 핸들러 객체 만들기 private static class MyHandler extends Handler { private final WeakReference<BackgroundThreadActivity> mActivity; public MyHandler(BackgroundThreadActivity activity) { mActivity = new WeakReference<BackgroundThreadActivity>(activity); } @Override public void handleMessage(Message msg) { BackgroundThreadActivity activity = mActivity.get(); if (activity != null) { activity.handleMessage(msg); } } }
▼ Handler 객체에서 전달받은 메시지는 메인 activity 의 handleMessage 에서 받아 처리합니다.
// Handler 에서 호출하는 함수 private void handleMessage(Message msg) { if (myTextOn) { myTextOn = false; myText.setVisibility(View.GONE); } else { myTextOn = true; myText.setVisibility(View.VISIBLE); } }
▼ 스레드와 Handler 클래스가 포함된 전체 activity 의 소스입니다.
import java.lang.ref.WeakReference; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.TextView; import android.widget.Toast; public class BackgroundThreadActivity extends Activity { BackgroundThread backgroundThread; TextView myText; private boolean myTextOn = true; //private static Handler handler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_background_thread); myText = (TextView) findViewById(R.id.mytext); Toast.makeText(this, "onCreate()", Toast.LENGTH_LONG).show(); } private final MyHandler mHandler = new MyHandler(this); // 핸들러 객체 만들기 private static class MyHandler extends Handler { private final WeakReference<BackgroundThreadActivity> mActivity; public MyHandler(BackgroundThreadActivity activity) { mActivity = new WeakReference<BackgroundThreadActivity>(activity); } @Override public void handleMessage(Message msg) { BackgroundThreadActivity activity = mActivity.get(); if (activity != null) { activity.handleMessage(msg); } } } // Handler 에서 호출하는 함수 private void handleMessage(Message msg) { if (myTextOn) { myTextOn = false; myText.setVisibility(View.GONE); } else { myTextOn = true; myText.setVisibility(View.VISIBLE); } } @Override protected void onStart() { super.onStart(); backgroundThread = new BackgroundThread(); backgroundThread.setRunning(true); backgroundThread.start(); Toast.makeText(this, "onStart()", Toast.LENGTH_LONG).show(); } @Override protected void onStop() { super.onStop(); boolean retry = true; backgroundThread.setRunning(false); while (retry) { try { backgroundThread.join(); retry = false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Toast.makeText(this, "onStop()", Toast.LENGTH_LONG).show(); } public class BackgroundThread extends Thread { boolean running = false; void setRunning(boolean b) { running = b; } @Override public void run() { while (running) { try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mHandler.sendMessage(mHandler.obtainMessage()); } } } }
반응형
'안드로이드 개발' 카테고리의 다른 글
안드로이드(Android) 백그라운드 스레드 소스 Runnable 이용해 구현 (0) | 2014.12.26 |
---|---|
안드로이드(Android) 백그라운드에서 Handler 를 통해 UI 변경 (1) | 2014.12.23 |
안드로이드(Android) This Handler class should be static or leaks might occur 해결 (6) | 2014.12.21 |
안드로이드(Android) Android.graphics.Color 에서 제공하는 컬러보기 샘플구현 (0) | 2014.12.17 |
안드로이드(Android) Activity 의 라이프사이클(LifeCycle) 알아보기위한 예제 (0) | 2014.12.16 |
안드로이드(Android) SurfaceView 와 Thread 이용해 화면에서 움직이는 공구현 (0) | 2014.12.12 |
댓글을 달아 주세요
2015.02.15 10:05 댓글주소 수정/삭제 댓글쓰기
비밀댓글입니다
sun.park20@gmail.com 2015.12.23 11:36 댓글주소 수정/삭제 댓글쓰기
잘봤습니다. static으로 만들때 memory leak이 떠서 뭔가 했는데 이거였군요.
ui랑 네트워크 쓰레드 조작 할 때, 핸들러, AsyncTask, 옵저버패턴등등 써봤는데 할때마다 해깔리고 새롭네요ㅠㅠ
네 감사합니다. ^^
2020.12.24 16:33 댓글주소 수정/삭제 댓글쓰기
비밀댓글입니다
설계 측면에서는 따로 구분하는 것이 좋은데, 샘플이고 Thread 클래스에 많은 기능이 없어서 같은 곳에서 사용했습니다. 그리고 참고하기도 편하거든요. 클래스 관리 차원에서는 분리하는 것이 좋겠죠. 어떤 에러가 발생하는지 모르겠지만 올려 보세요.
앗 해결했습니다!! 도움 감사합니다 ㅎㅎ