본문 바로가기

개발이야기/Android

안드로이드 HandlerThread 스레드 사용법

Android HandlerThread

android HandlerThread는 Thread class를 상속하고 내부에서 Looper.preapare()과 Looper.loop()를 실행하는 Looper 쓰레드이다. HandlerThread는 UI와 관련없지만 단일스레드에서 순차적인 작업이 필요할 때 사용한다.


Example)


상기와 같이 인스타그램에 좋아요 버튼이 있다. 좋아요 버튼을 누르면 실시간으로 DB에 반영된다고 가정하자. 


개발자는 UI를 블로킹하지 않도록 별도 쓰레드에서 DB에 반영하도록 할 것이다. 사용자가 좋아요를 마구마구 바꾸기도 한다. 만약 좋아요 상태가 바뀔 때 마다 스레드를 생성(new instance and start)하거나 스레드가 스레드(get instance and start)를 가져다가 DB에 반영한다면 어떤일이 벌어질까? 스레드가 start()를 실행한 순서대로 실행되지 않기 때문에 사용자가 좋아요->안좋아요->좋아요 했어도 DB에 반영될 때는 네트워크 상황과 같은 요인 때문에 좋아요->좋아요->안좋아요 순으로 잘못 반영될 수도 있다.


실행순서를 순차적으로 맞추어야 오작동을 막을 수 있는데 이 때, HandlerThread를 사용하여 해결가능하다.


Example Code)

private Handler likeHandler;
private HandlerThread handlerThread;
 
@Override
public void onCreate(Bundle savedInstanceState){
    ..
    handlerThread = new HandlerThread("Like Processing Thread");
    handlerThread.start(); // create될 때 백그라운드에서 thread가 돌도록 start()
    likeHandler = new Handler(handlerThread.getLooper()){
        @Override
        public void handleMessage(Message message){
            MessageLike messageLike = (MessageLike) msg.obj;
            LikeDao.updateMessageLike(messageLike.id,messageLike.like); //DB에 반영
        }
    };
}
 
private class MessageAdaptor extends ArrayAdaptor{
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
    ...
    holder.like.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view){
            boolean checked = ((CheckBox)view).isChecked();
            Message message = likeHandler.obtainMessage();
            message.obj = new MessageLike(item.id,checked);
            likeHandler.sendMessage(message); // 체크박스를 선택/해제 할 때 마다 핸들러에 메시지 전송
        }
    });
}
 
@Override
protected void onDestory(){
    handelrThread.quit();
    super.onDestroy();
}


마치 Queue가 동작하는 것 처럼 수행하지만, 따로 Queue를 만들지 않더라도 강력하게 쓰레드를 제어할 수 있다.

(사실 Looper가 MessageQueue를 만들어서 수행하고있음)



End of Document.