이 글은 PC 버전 TISTORY에 최적화 되어있습니다.
서론
Handler와 Looper의 필요성
핸들러를 생성하는 스레드만이 다른 스레드가 전송하는 Message와 Runnable 객체를 받을 수 있다.
Handler와 Looper 이 복잡한 개념이 왜 필요하나 싶으실텐데요. 위 그림을 보면 안드로이드 내에서 Thread 백그라운드 처리에 Handler와 Looper가 왜 필요한지 명확히 아실 수 있으실겁니다. 병렬 처리로 돌아가고 있는 Main과 Sub Thread에서 같은 textView 를 setText 했을 때 어떤 Thread의 것을 따라야 할까요? 이러한 동기화 문제를 처리하기 위해 안드로이드에서는 메인 스레드에서만 UI 작업이 가능하도록 제한한겁니다. Handler와 Looper를 이용해 Sub Thread에서 Main Thread로 UI 처리 작업을 전달하던지, Main Thread 내에서 자체적으로 처리하던지 해야하는 것 입니다.
Handler와 Looper의 동작 과정
Handler는 단어 의미 그대로 무언가를 처리하는 놈 입니다. 이 친구는 Message와 Runnable 객체를 처리합니다. Runnable 메시지(Thread(Runnable runnable) 생성자로 만들어서 Runnable 인터페이스를 구현한 개체를 생성하여 상속 받은 스레드는 추상 메서드 run( )을 반드시 구현해야하는 것.) 는 run( ) 메서드를 호출해 처리하고, Message는 handleMessage( ) 메서드를 이용해 처리합니다. 그럼 어떻게 흐름이 진행되는지 정리해보도록 하겠습니다.
메시지는 다른 스레드에 속한 Message Queue에서 전달됩니다.
MessageQueue에 메시지를 넣을 땐 Handlerdㅢ sendMessage( )를 이용합니다.
Looper는 MessageQueue에서 Loop( )을 통해 반복적으로 처리할 메시지를 Handler에 전달합니다.
Handler는 handleMessage를 통해 메시지를 처리합니다.
여기서 중요한 점은 Handler는 의존적이라는 것 입니다. Handler 혼자서는 아무것도 못하는 바보이죠. MessageQueue가 있어야 하고, 또 그 메시지를 전달해 줄 Looper가 없으면 Handler의 handleMessage( )는 그야말로 거미줄을 치는 것입니다. 즉 Handler는 Thread와 Looper, MessageQueue 가 꼭 필요합니다.
Looper의 역할
Looper 생성법
Handler는 무조건 Looper와 MessageQueue가 필요하므로 어떤 스레드와 연동되기 위해선 Looper가 꼭 필요하다는 것을 알 수 있습니다. 그렇다면 스레드에 Looper를 포함시키려면 어떻게 해야할까요?
Thread t = new Thread(new Runnable(){ @Override public void run() { Looper.prepare(); handler = new Handler(); Looper.loop(); } }); t.start();
HandlerThread t = new HandlerThread("My Handler Thread"); t.start(); handler = new Handler(t.getLooper());
단독 사용한 Handler?
public class MainActivity extends AppCompatActivity { Handler mHandler = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new Handler(); Thread t = new Thread(new Runnable(){ @Override public void run() { // UI 작업 수행 X mHandler.post(new Runnable(){ @Override public void run() { // UI 작업 수행 O } }); } }); t.start(); } }
이런 식으로 메인 스레드에서 Handler를 생성하면 해당 Handler는 호출한 스레드의 메시지큐와 루퍼에 자동 연결 되므로 다른 스레드에서 Handler를 통해 메시지를 전달하면 메인 스레드(UI 스레드)에서 UI 작업을 가능하게 하는 것입니다.
다른 방법에 대해서는 Handler 사용법 포스팅을 참고하시길 바랍니다.
참고할만한 사이트
'Frontend > Android' 카테고리의 다른 글
[안드로이드] 안드로이드 메모리 관리 (Weak Reference와 Soft Reference) (0) | 2016.07.08 |
---|---|
[안드로이드] AsyncTask란? (개념 및 사용법) (3) | 2016.07.07 |
[안드로이드] runOnUiThread란? (개념과 사용법) (5) | 2016.07.07 |
[안드로이드] 스레드(Thread) 개념 및 사용법 (5) | 2016.07.06 |
[안드로이드] ANR의 의미와 예방 (2) | 2016.07.05 |
[안드로이드] 리스트뷰 성능최적화 (Convertview와 ViewHolder Pattern의 이해) (2) | 2016.07.05 |