Android UI 작업은 무!조!권 Main Thread 에서 작업해야 한다.
왜 그럴까?
Worker Thread에서 Handler를 사용하여 메세지를 전달한다. 전달된 메세지는 Main Thread를 통해 작업을 처리한다.
다른 스레드에게 메세지를 전달하려면
결국 , Thread에서 만든 Handler를 순차적으로 넣어 놓은 것을 다시 빼서 실행 시키는 것이다.
🍏 그래서
Handler1 가 Main Thread 라면 Handler2,Handler3은 다른 작업 쓰레드이다.
Hadndler 2 or 3 에서 UI 작업을 요청하면 Message Queue 에 쌓이고
이를 Looper 가 실제 UI작업을 관리하는 handlerMessage를 통해 MainThread에서 순차적으로 실행 시킨다.
Handler의 생성자에 Looper가 전달되는데 이는 모든 Handler가 동일한 Looper를 이용하게 된다.
🍏 그림 처리 순서
(Handler1, Handler3, Handler2) -> Message Queue -> Looper(FIFO)처리 -> handlerMessage
잠깐 코드 보자
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// something..
}
}, 1000);
위에서 말한대로 Handler 생성자에 Looper를 넣게 된다.
위의 예제는 Delay를 주는 코드이다.
Handler.sendMessage(Message msg)
: Message 객체를 message queue에 전달하는 역할
Handler.sendEmptyMessage(int wht)
: Message의 wht 필드를 전달하는 함수
post()
: post()는 Message 객체가 아닌 Runnable 객체를 Message queue에 전달한다.
ex) Handler.post(new Runnable()) // 위에서 본 코드.
new Thread(new Runnable(){
@Override
public void run() {
WHandler whandler;
whandler = new WHandler();
whandler.post(new Runnable(){
@Override
public void run() {
//여기서의 UI 작업은 안된다.
}
}
}
}
당연히 안된다. UI작업은 메인스레드에서만 가능하기에.
하고싶다면 메인 스레드에서 해야 한다.
new Thread(new Runnable(){
@Override
public void run() {
// 여기서는 UI 작업 불가.
mainHandler.post(new Runnable(){
@Override
public void run() {
//여기서의 UI 작업은 가능.
}
}
}
}
mainHandler로 UI작업을 진행한다
Work Thread내부에서 Main Thread의 Handler를 통해 Runnable 객체가 전달한다.
메인 스레드의 Looper가 Runnable 객체를 꺼내서 run()을 실행한다
MainThread
Handler mainHandler = new Handler()
Work Thread
mainHandler.post(new Runnable())
Main Thread의 mainHandler를 통해 run()을 실행하는 격이다.