Handler class
- Handler는 Message를 MessageQueue에 넣는 기능과 MessageQueue에서 꺼내 처리하는 기능을 함께 제공한다.
Handler 생성자
- Handler에는 기본 생성자 외에도 Handler.Callback 이 전달되는 생성자도 있고, Looper가 전달되는 생성자도 있다.
- Handler()
- Handler(Handler.Callback callback)
- Handler(Looper looper)
- Handler(Looper looper, Handler.Callback callback)
- 1~3번째 생성자는 파라미터 개수가 가장 많은 4번째 생성자를 다시 호출한다.
- 기본 생성자는 바로 생성자를 호출하는 스레드의 Looper를 사용하겠다는 의미이다.
- Handler 기본 생성자는 앱 프로세스가 시작할 때 ActivityThread에서 생성한 main Looper를 사용한다.
- Handler 기본 생성자는 UI작업을 할 때 많이 사용된다.
백그라운드 스레드에서 Handler 기본 생성자 사용하려면 Looper 필요
백그라운드 스레드에서 Handler 기본 생성자를 사용했을때 Looper가 준비되어 있지 않으면 RuntimeException이 발생
이를 해결하기 위해서 Looper.prepare()를 실행해서 해당 스레드에사 사용할 Looper를 준비해야 한다.
내부적으로 prepare() 메서드는 MessageQueue를 생성하는 것 외에 별다른 동작을 하지 않는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class LooperThread extends Thread{ public Handler mHandler; public void run(){ Looper.prepare(); mHandler = new Handler(){ public void handleMessage(Message msg){ // 여기서 Message 처리 } }; Looper.loop(); } }
- LooperThread에서 스레드를 시작하면 Looper.loop()에 무한 반복문이 있기 때문에 해당 스레드는 종료되지 않는다. 그리고 mHandler에서 sendXxx(), postXxx()메서드를 사용하면 스레드내에서 handleMessage를 실행한다.
호출 위치가 메인 스레드인지 확인이 쉽지 않음
- 백그라운드 스레드에서 Handler 기본 생성자를 쓴 경우 Looper가 준비되지 않아 RuntimeException을 만나는 경우가 있다.
- 백그라운드에서 Looper를 생성해도 UI를 업데이트하는 작업을 하면 CalledFromWrongThreadException이 발생하게 된다. 이를 해결하기 위해서는 Handler의 세 번째 생성자인 Handler(Looper looper)를 사용하면된다.
1 2 3 4 5 6 7 8
public void process(BadgeListener listener){ int count = ... new Handler(Looper.getMainLooper()).post(new Runnable(){ public void run(){ listener.updateBadgeCount(count); } }); }
- Handler 생성자에 Looper.getMainLooper()를 전달하면, 메인 Looper의 Message Queue에서 Runnable Message를 처리한다.le Message를 처리한다.