본문 바로가기
Android/안드로이드 프로그래밍 Next Step

[Next Step] 3. HandlerThread 클래스

by Diane_KIM 2023. 8. 9.

https://www.youtube.com/watch?v=n0mkYSjldeA

Looper를 가진 스레드면서 Handler에서 사용하기 위한 스레드

 

HandlerThread 사용방법

private HandlerThread handlerThread; // 1. HandlerThread를 변수로 선언

public Processor() {
	handlerThread = new HandlerThread("Message Thread"); // 2. 생성자안에서 초기화
    handlerThead.start();
}

public void process() {
	...
    
    // 3. 핸들러를 이용해 메세지 처리하는 메소드를 생성
    // 4. 핸들러 생성자에 HandlerThread의 Lopper 전달
    
    new Hanlder(handlerThread.getLooper()).post(new Runnable() {
        // 5. Handler에서 Message 보냄
        // 6. HandlerThread에서 생성한 스레드에서 처리
        
    	@Override
        public void run() {
        	...
        }
    }

}

 

HandlerThread 프레임워크 소스

public class HandlerThread extends Thread {

    Looper mLooper;

    @Override
    public void run() {
        Looper.prepare(); // 1. run 메서드에서 Lopper 준비
        synchronized (this) { // 2. 멤버변수에 루퍼를 대입시킬때까지 스레드 중지
            mLooper = Looper.myLooper();
            notifyAll(); // 3. 대기하는 스레드 깨움
        }
        Looper.loop();
    }

    public Looper getLooper() {
        if (!isAlive()) { // 4. HandlerThread에서 start()호출했는지 체크
            return null;
        }

        synchronized (this) {
        
	        // 5. HandlerThread가 start()하고, 멤버변수 mLooper에 값이 대입되어있지 않다면    
            while (isAlive() && mLooper == null) { 
                try {
                    wait(); // 6. 대기
                } catch (InterruptedException e) {
                }
            }
        }
        
        // 7. HandlerThread 시작됐고, 멤버변수에 값이 있다면 return
        return mLooper;
    }

	// 8. getLopper() 이용해 값이 있을때만 종료
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
}

순차 작업에 HandlerThread 적용

HandlerThread에서 Message 처리

private Handler favoriteHandler;
private HandlerThread handlerThread;

@Override
public void onCreate(Bundle savedInstanceState) {
	...
    handlerThread = new HandlerThread("Favorite Processing Thread"); // 1. HandlerThread 생성
    handlerThread.start(); // 2. 스레드 시작
    
    // 3. HandlerThread에서 만든 Looper를 Handler 생성자에 전달
    favoriteHandler = new Handler(handlerThread.getLopper()) {
    	
        @Override
        public void HandleMessage(Message msg) {
            // 5. 메세지 받으면 db에 반영
        	MessageFavorite messageFavorite = (MessageFavorite) msg.obj;
            FavoriteDao.updateMessageFavroite(messageFavroite.id, messageFavroite.favorite);
        }
    };
}

private class MessageAdapter extends ArrayAdapter<Message> {

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ...
        holder.favorite.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                boolean checked = ((CheckBox)) view).isChecked();
                Message message = favroiteHandler.obtainMessage();
                message.obj = new MessageFavorite(item.id, checked);
                favoriteHandler.sendMessage(message); // 4. 체크박스 클릭시 핸들러에 메세지 전달
            }
        });
    }
}

@Override
protected void onDestroy() {
	// 6. Activity 종료시 핸들러 스레드의 quit() 메서드 이용해서 Looper 종료
    handlerThread.quit();
    super.onDestroy();
}