Android

HandlerThread 대해서

Machine_웅 2023. 3. 22. 21:31
728x90
반응형

HandlerThread에 대해서

 

Main Thread는 HandlerThread 구조를 가진다고 하였다.

그것이 왜 필요한지 부터 설명토록 하겠다.

Thread의 생명주기는 run() 함수내에서 끝난다. 아래의 그림을 보자.

위 처럼 run() 진입이 Thread의 생성이며,  run()함수의 끝이 Thread 종료이다.

 

 

 

만일 Main Thread가 위처럼

run()함수에서 끝나버리면

Android Appliction이 유지 될 수 없지 않겠는가?

 

바로 아래를 보자.

 

 

위와 같이 run() 함수에서

어떤 일을 계속 처리하기 위해서

while(true) 와 같이 계속 loop 를 돌게 된다.

 

 

 

 

 

 

 

계속 바로 아래를 보자.

 

 

위와 같이 마냥 loop만 돌고 있는 것이 아니라,

looper는 처리해야 할 일을 쌓아둘 Queue를 하나 가지고 있다.

 

 

 

 

 

 

 

 

계속 아래를 보자.

 

 

Queue에는 처리해야할 일 즉 job들을 어떤 누군가가 넣게 된다.

 

 

 

 

 

 

 

 

 

 

계속 아래를 보자.

 

looper는 계속 looping하면서 queue에 들어가 있는 job들을 하나씩 꺼내서

처리하는 것이다.

 

위와 같은 구조는 모든 platform에서 일반적인 구조 이다.

즉 Android에서도 위와 같은 구조를 Main Thread가 가지고 있다.

 

 

 

 

 

 


 

아래의 Class들이 그런 일들을 하고 있는 것이다.

 

위의 과정을 상기하면서 하나씩 Class의 역할을 알아가 보자.

 

 

 

자 HandlerThread Class의 역할은 다음과 같다.

즉 계속 반복해서 loop를

돌고 있는 Looper를 하나 가지며,

 

Looper 안에는

MessageQueue라고 하는

Queue를 가진다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Message Class는 무엇일까?

위와 같이 Queue에 들어갈 Job 단위 이다.

 

Message에는 처리해야할

코드들이 들어가 있다.

 

(참고로 Message Class는 Parcelable을 상속 받았다.

 

이전에 직렬화 강좌에서

이 것을 상속 받은면

다른 Process 혹은

네트워크 등으로

객체 전달이 가능하다고 했다.

 

 그렇다면 이 Message는 바로

다른 Process로 전달이 가능한 데이터 덩어리인 것을 알수 있을 것이다.)

 

 

 

Handler Class는 무엇일까?

Queue에 Message를 집어 넣는 역할을 한다.

위에 1~8번의 Handler Class의 함수를 사용하여 Queue에 메시지를 넣게 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

참고로 메시지에는 메시지가 처리해야할 시간을 설정할 수도 있다.

 

그 것이 바로 4,5,7,8번 함수에 들어가는

uptimeMillis와  delayMillis 이다.

uptimeMillis 는 실행될 절대적 시간이며,

delayMillis는 현재 시간을 기준으로 해당 시간이후에 실행된다는 의미이다.

어쨌는 사용 방법은 나중에 해당 객체를 사용할때 확인하도록 하자.

 

마지막으로 Looper Class는 무엇일까?

Looper는 while()문 그 자체이다.

 

이렇게 반복적으로 Looping 하면서

 

Queue에 메시지를 하나 꺼내 실행시켜 주는 역할을 하는 것이다.

 

자 쉽게 이해가 되었을 것이다.

 

 

 

 

 

 


 

자 그렇다면 Job 단위라고 하는 Message에 대해서 살펴 보자.

Message가 처리되는 방법은 두가지가 존재한다.

 

첫번째는 위의 두가지 정보를 설정함으로써 가능하다.

when이라는 변수를 통해 자신이 실행되는 시점의 시간을 설정할 수 있다.

실행되어야 할 시간이 되면 실행되는 코드가 바로 callback이다.

 

callback는 Runnable이다.

Runnable은 Interface이며, 내부에 구현해야할 함수는 run()이다.

즉 run()함수를 Message객체를 생성할때 구현해 주면  looper가 실행해 주는 것이다.

 

 

 

자 두번째를 살펴보자.

두번째는 위의 7가지 값이 사용된다.

target은 Handler이다.

Handler는 Queue에 Message를 넣어주는

객체라고 하였다.

 

 

그 밖에 기능으로 Handler를 생성할때 위와 같이

public void handleMessage() 함수를 overriding 하여 구현해 줄 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

첫번째 방법에서 callback 즉 Runnable 객체의 run()을 구현해 주고 실행이 되었다.

두번째 방법은 바로 handleMessage() 함수를 구현하여 실행하게 되는 것이다.

 

what는 handleMessage에서 작업을 구분할 명이다.

위의 예제는 "0"이라고 하였지만 당연히 구현시에는 "static int  DRAW_RECT = 0" 과 같이

정의 하여 사용해야 한다.

 

arg1, arg2, obj, data 등은 handleMessage함수로 전달할 데이터 들이다.

arg1, arg2는 int 형이므로 정수 데이터를 쉽게 전달할 것이고

obj는 Object 형이므로 여러가지 객체를 전달할 것이다.

 

data는 Bundle 형이므로 여러가지 데이터 덩어리를 넣어서 전달할 수 있다.

(Bundle에 대해서는 이전 강좌에서 설명하였다. 모르면 바로 참조하기 바란다.)

 

위의 sample 코드를 살펴보면 쉽게 이해 될 것이다.

 


 

자 전체적으로 처리되는 과정을 다시 살펴 보자.

1번에서 HandleThread를 생성하면,

2,3,4 번과 같이 MessageQueue가 생성되고, Looper가 생성되고 결국 HandlerThread가 생성이 될 것이다.

5번에서 해당 Thread를 실행하기 위해 HandlerThread를 start하게 되면

6번과 같이 Thread의 run()이 실행되고

7번과 같이 Looper가 계속 반복하여 MessageQueue에 메시지를 꺼내가려고 할 것이다.

               (Message가 없으면 잠시 wait하게 된다.)

8번에서 Handler를 생성하면

9번과 같이 MessageQueue에 메시지를 넣기 위하여

         Handler는 Looper를 참조하게 된다.

         (Looper는 MessageQueue를 참조하므로 결국 메시지를 넣을 수 있는 참조가 된다.)

 

10번에서 처리해야할 Job 단위인 Message를 하나 생성한뒤

        처리해야할 코드를 넣어준다.

        코드를 넣는 방법은 위에서 두가지라고 했다.

        (callback : Runnable 객체의 run()을 구현해서 넣는 방법과,

         target : Handler의 handleMessage()를 구현하는 방법이 있다.)

        두가지 방법을 모두 넣게 되면 callback이 실행된다.

11번에서 Handle.sendMessage()함수 등을 이용해서

         MessageQueue에 메시지를 넣으면

12번에서 Looper가 넣은 메시지를 하나꺼내서

13번과 같이 callback이 구현되어 있으면 callback의 run()함수를 실행해 주고

                 target이 구현되어 있으면 target의 handleMessage()함수를 실행해 준다.

 

이 것이 전체적인 구조이며, MainThread는 위와 같은 구조를 가진다.

 

아래는 그 증거를 보여 주고 있다.

내가 테스트로 com.test.ThreadTest 라는 패키지가 실행된 상태인 경우,

(아무 패키지를 실행해도 된다.)

1번과 같이 DDMS를 선택하고

2번에서 Devices 탭의 해당 패키지 Process를

3번과 같이 선택한다.

4번과 같이 Threads라는 탭을 선택하고

5번과 같이 "update Threads"버튼을 누른다.

이렇게 하면 해당 Process 내 생성된 Thread를 모두 보여준다.

6번에 main Thread를 선택하면

7번과 같이 해당 Thread에서 생성된 객체들을 모두 보여준다.

자세히 보면 MessageQueue 객체와 Looper 객체가 생성된 것을 볼 수 있다.

 

Main Thread에서만 HandlerThread를 사용하는 것이 아니다.

Android 전역전으로 HandlerThread 구조를 적절히 사용한다.

이런 구조는 활용할 범위가 많다는 것을 기억하자.

 

 

 


https://m.cafe.daum.net/superdroid/aAfL/98?svc=cafeapi 

 

16. Activity에 대해서 - Thread 와 Android Main Thread

슈퍼드로이드 카페의안드로이드 강좌가 책으로 나왔습니다.도서명 : 이것이 안드로이드다.도서링크 :http://www.yes24.com//24/goods/13950202==================================================================================

m.cafe.daum.net

 

728x90
반응형