Android: Handler

ericbyeric·2021년 6월 28일
0

Android

목록 보기
4/6
post-thumbnail

Prerequite: Thread

Handler

Before diving into learning what handler is you have to know thread first :)

Background thread에서 다른 Thread에 소속되어 있는 UI를 조작하려고하면 해당 Background thread가 죽었어.. 그 이유는..?
=> 동기화 때문이야!

일어날 수 있는 문제)
A Thread, B Thread 이렇게 2개의 thread가 있다고 하자.
이 두개의 thread에서 동시에 하나의 View component의 값을 바꾸면 어떤 값으로 수정되야 될지의 문제가 생기겠지?
그래서 Background thread에서 연산은 가능 하지만 다른 thread에 속해있는 UI의 View component의 값을 변경 할 수 없어

그럼 이걸 어떻게 해결할 수 있을까?
=> Background thread에서 연산된 값을 Main thread로 알려주면 되지 않을까?
=> 이걸 알려주려면 thread간에 통신이 되어야 겠지?
=> 이 통신을 누가 도와줄까?
=> Handler!

How handler works

Handler는 자신을 생성하는 Thread에 삽입되며 해당 Thread의 message queue를 통해서 다른 thread들과 소통 할 수 있어.
일반적으로 다른 thread로 부터의 message를 수신하고, 자기 자신이 보낸 message를 수신 할 수도 있어

Message 확인 메서드 [수신]

void handleMessage(Message msg)

message가 도착하면 위의 메서드가 호출되
Message: thread간 통신내용이 저장되는 object

Message Field설명
int what메세지의 의미. 의미가 따로 정해져있는건 아니다. 다른 Handler와 충돌할 위험 없음
int arg1메세지 추가 정보
int arg2메세지 추가 정보
Object abj메세지가 정수로서 표현하지 부족할때 임의의 객체 전송
Messenger replyToMessage 응답을 받을 Object 지정

Message 전송 메서드 [송신]

boolean Handler.sendEmptyMessage(int what)  // send a simple message
boolean Handler.sendMessage(Message msg)    // send a complex message
boolean Handler.sendMessageAtFrontOfQueue(Message msg)  // qriority message

Handler.sendMessageAtFrontOfQueue의 경우 일반적으로 Message는 Queue에 순차적으로 처리되나 우선 처리되야할 Message가 있을때 사용한다

위의 3가지 Message 전송 메서드를 이용해 Message를 전송하면 Handler의 handleMessage 메서드가 호출되어 Message를 수신한다.
Message에 따라 구현을 달리 할수 있겠죠? :)

Handler Example

Example with sendEmptyMessage(int what)

Thread에 Handler를 적용!

class BackRunnable implements Runnable{
	public void run()
        {
            while(true)
            {
                b_thread_val++;
                m_handler.sendEmptyMessage(0);
                // tv_b_thread_val.setText("Value in back thread: " + b_thread_val);
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
        
        Handler m_handler = new Handler()
        {
        	public void handleMessage(Message msg)
            {
            	if(msg.what == 0)
                {
                	tv_b_thread_val.setText("value in back thread :" + b_thread_val);
                }
            }
        }
}

Android: Thread 게시글에 포함된 예시를 가져와서 Handler를 적용해 보았어!
Runnable object에서 m_handler.sendEmptyMessage(0) 메서드로 Handler에 "0"이라는 값(msg.what)을 전달하고 Handler내부의 HandleMessage메서드로 Message를 받아서 이후 동작을 구현 할 수 있어.

이렇게 구현했을때 좋은점이 뭘까?
=> Background thread가 연산을 해서 Main thread한테 부탁을해. 그러면 내가 원하는 값을 출력할 수 있어.
=> 즉 UI를 바꾸려는 동작이 Main thread로 "일원화"되어 동기화문제가 해결되!

Before running the app
m_thread_val: 0
b_thread_Val: 4

After running the app
m_thread_val: 0
b_thread_val: 13

오 버튼을 안누르고도 b_thread_val가 증가하네! :) 이게 동기화야~

Example with sendMessage(Message msg)

class BackRunnable implements Runnable{
	public void run()
        {
            while(true)
            {
                b_thread_val++;
                Message msg = new Message();
                msg.what = 0;
                msg.arg1 = b_thread_val;
                m_handler.sendMessage(msg);
                // tv_b_thread_val.setText("Value in back thread: " + b_thread_val);
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
        
        Handler m_handler = new Handler()
        {
        	public void handleMessage(Message msg)
            {
            	if(msg.what == 0)
                {
                	tv_b_thread_val.setText("value in back thread :" + msg.arg1);
                }
            }
        }
}

Runnable을 implement한 thread에서 Message object를 생성하여 what과 arg1필드에 값을 넣어주고 m_handler에게 sendMessage(msg)메서드를 통하여 Message를 전송했어.

profile
인생의 해상도를 올려볼까나

0개의 댓글