안드로이드 지식 공유
HandlerThread 의 활용
우리가 전편에서 구경했던? Handler 는 매우 쉽고 간편하게 비동기적 처리를 담당해주는 고마운 녀석이 었습니다. 그러나 백그라운드 작업에서 핸들러를 설정하려면 여러가지로 셋팅해줘야 할 부분들이 생기죠. 쓰레드의 동작 까지 신경써야 합니다. 그리하여 우리는 HandlerThread 라는 녀석과 만나게 됩니다.
https://developer.android.com/reference/android/os/HandlerThread
이 녀석은 쉽게말해 우리가 쓰레드를 생성하고 그안에 핸들러 셋팅까지 했던 것을 자동으로 해주는 고마운 친구 입니다. 즉 Thread Looper MessageQueue 의 복잡함을 자동으로 관리해준다는 말이죠. 동작방법은 너무도 쉽습니다.
HandlerThread handlerThread = new HandlerThread("HandlerThread-1");
handlerThread.start();
어디서 많이 보던 start 아닙니까? ㅎㅎ 맞습니다. 우리가 쓰레드 동작시 사용하던 그 방식과 유사합니다. 핸들러쓰레드의 경우도 마찬가지로 핸들러사용시 따랐던 기준을 그대로 따릅니다. 우리가 해주지 않을뿐 내부적으로 looper 와 MessageQueue를 가지고 있고 이는 순차적으로 처리되지요. 골치 아픈 동기화따위 신경쓸 필요가 없습니다ㅎㅎ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | private class TestHandlerThread extends HandlerThread{ private static final int READ = 1; private static final int WRITE = 2; private Handler mHandler; @Override protected void onLooperPrepared() { super.onLooperPrepared(); mHandler = new Handler(getLooper()){ @Override public void handleMessage(Message msg) { switch(msg.what){ case READ: //내용을 읽습니다... break; case WRITE: //내용을 작성합니다... break; } } }; } public void read(){ mHandler.sendEmptyMessage(READ); } public void write(int i){ mHandler.sendMessage(Message.obtain(mHandler, WRITE, i)); } } | cs |
이너클래스를 생성하고 그 안에 HandlerThread 를 상속합니다. 그리고 반드시 onLooperPreared() 메서드를 오버라이드 하여 구현해 주셔야 합니다. 여기서는 Handler 를 생성하고 getLooper()로 바인딩 해준뒤 메세지를 처리하고 있네요. 메세지는 아래와 같은 경우 작업이 진행되겠죠.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ... private Button btnRead; private Button btnWrite; private int mCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_handler_thread); mTextValue = findViewById(R.id.text06); btnRead = findViewById(R.id.btnRead); btnRead.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { onButtonClickRead(view); } }); btnWrite = findViewById(R.id.btnWrite); btnWrite.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { onButtonClickWrite(view); } }); mThread = new TestHandlerThread(); mThread.start(); } /** * ui스레드에서 더미값을 기록한다 * @param v */ public void onButtonClickWrite(View v){ mThread.write(mCount++); } /** * ui스레드에서 읽기를 시작한다 * @param v */ public void onButtonClickRead(View v){ mThread.read(); } |
버튼을 두개 만들어 읽고 쓰는 작업을 시켰습니다. public 메서드를 통해 핸들러쓰레드의 만들어두었던 public 메서드 들을 통해 핸들러 에게 정확히 전달 되겠죠? 그러면 그 핸들러는 해당 작업을 진행할 겁니다. 이제 우리는 쓰레드를 만들고 할 필요 없이 유연한 비동기 로직을 만들었습니다.
아 한가지 빼먹은 부분은 이 핸들러 쓰레드를 다 사용하고 나서 뒷처리 입니다. 핸들러쓰레드의 경우는 루퍼의 종료를 통해 쓰레드의임무도 다하게 됩니다. 핸들러는 quit()를 통해 루퍼의 종료를 선언 할 수 있죠.
1 2 3 4 5 6 7 8 | /** * 액티비티와 함께 백그라운드 스레드가 종료됨을 보장한다. */ @Override protected void onDestroy() { super.onDestroy(); mThread.quit(); //mThread.quitSafely() } | cs |
이런식으로 액티비티와 생명주기를 같이 할 수도 있습니다. 모든 작업이 끝났다면 말이죠. 핸들러를 통해 마지막 종료 태스크를 전달 할 수도 있겠죠? Looper.myLooper()를 통해 핸들러 자신과 연결된 루퍼를 가져옵니다. 그리곤 종료 명령을 때려버립니다.ㅎㅎ
1 2 3 4 5 6 7 | handler.post(new Runnable(){ @override public void run(){ Looper.myLooper().quit(); } }); | cs |
이렇게 말이죠. 한번 종료된 핸들러쓰레드와 친구들은 한번 종료되면 다시 사용할 수 없습니다. 다시 시작할때는 분명 Exception 친구를 만나게 될 것입니다. ^^
잘 사용하면 너무 편한 핸들러 , 핸들러 쓰레드에 대해 알아보았습니다. 비동기 처리를 간단하게 구현할 수 있지만 사실은 개발하는 입장에서 신경써야 할게 상당히 많습니다. 한마디로 노간단... 다음 시간에는 좀 더 활용도가 높은 AsynTask 에 대해 알아보겠습니다. 그럼 이만.
'HELLO_WORLD > 안드로이드_Android' 카테고리의 다른 글
[지식공유] 자바 메모리 Stack 과 Heap 영역에 대하여 (0) | 2018.08.18 |
---|---|
[지식공유] 안드로이드 웹뷰 핀치 줌 인 / 아웃 (0) | 2018.08.18 |
[지식공유] UI쓰레드에서 긴작업을 하면 안되는 이유 (0) | 2018.08.14 |
[지식공유] Handler 에 대한 이해 (0) | 2018.08.11 |
[초보강좌] 1. 일단 만들어 봅시다 (0) | 2018.08.09 |
댓글0