안드로이드/이론관련

핸들러(Handler)

닉네임못짓는사람 2021. 7. 7. 16:56
반응형

이번 글에서는 Handler에 대해서 알아보도록 하자.

 

이전에 Thread와 Mutli Thread에 관한 글을 포스팅한 적이 있다.

Android에서도 Application의 성능을 위해 Multi Thread를 활용하는데,

UI를 업데이트할 때는 반드시 Main Thread에서 작업을 수행한다.

Main Thread는 Android에서 UI를 수정할 수 있는 유일한 Thread이기 때문에 UI Thread라고 부르기도 한다.

 

Multi Thread환경에서 모든 Thread가 UI 업데이트 작업을 수행하게 되면

Thread간 교착상태(DeadLock)나 경쟁상태(Race Condition)등의 문제에 빠질 수 있기 때문이다.

여기서 둘에 대해 간단히 설명하자면

 

경쟁상태는 둘 이상의 Thread에서 하나의 데이터(예를 들면 변수)등에 접근했을 때

적절한 Scheuling이 이루어지지 않으면 의도치 않은 결과가 나타나는 것을 이야기한다.

(변수 C에 A, B Thread가 각각 1과 3이란 값을 입력할 때 Scheduling을 해주지 않으면 이 값을 알 수 없다.)

 

교착상태는 둘 이상의 Thread가 자원을 획득하려 할 때 서로 상대방의 작업이 끝난 뒤

자원을 획득하려 하기 때문에 작업이 동결되는 경우를 이야기한다.

(A가 자원 C를 획득하고 있고, B가 자원 D를 획득하고 있을 때 A는 자원 D가 필요하고

B는 자원 C가 필요한 경우 서로 상대방의 작업이 끝나는 것을 기다리기 때문에 이러한 상황이 발생한다.)

 

다시 본론으로 돌아와서 이러한 문제점 때문에 Android에선 UI Thread만 UI업데이트 작업이 가능한데,

이를 다른 Thread(Worker Thread)에서도 수행할 수 있도록 해주는 것이 Handler이다.

핸들러 (Handler)


Handler는 Android에서 Thread간 통신을 위해 사용하는 클래스, 간단하게 말하면 메세지 전달자 정도로 볼 수 있다.

위에서 말한 Worker Thread에서 UI업데이트 작업을 수행한다는 작업은 사실 적절하지 않고,

Worker Thread에서 UI업데이트 작업을 UI Thread로 보내서 처리한다는 말이 적절할 것이다.

 

예를 들어 Worker Thread에서 아래와 같은 UI업데이트 작업을 실행하려 한다고 해보자.

textView.setText("Worker")

이를 단순히 실행하면 위에서 말한 이유 등을 방지하기 위해 Android Studio에서 Error가 발생한다.

때문에 우리는 이 Message를 Handler를 통해 Message Queue에 넣어주어야 한다.

Message Queue는 Handler가 전달하는 Message를 보관하는 FIFO(First In FIrst Out)방식의 저장공간이다.

 

여기서 Handler는 Handler객체를 만든 Thread(UI Thread)와 해당 Thread의 Message Queue에 바인딩된다.

Worker Thread에서 수행할 작업(Message)을 UI Thread의 Handler에 요청하면 Handler는 이를 Message Queue에 저장한다.

 

그리고 이렇게 차곡차곡 쌓인 Message들을 다시 Looper가 하나씩 꺼내서 다시 Handler로 전달한다.

Looper는 Thread내에서 주기적으로 MessageQueue를 탐색하여 작업이 생기면 이를 Handler로 전달하는 역할을 한다.

 

또한 Thread당 하나의 Looper만 가질 수 있으며, UI Thread를 제외한 Worker Thread들은 Looper를 가지지 않는다.

Handler는 이 Looper가 전달한 Message들을 하나씩 받아서 처리하게 된다.

 

간단하게 위 작업들을 그림으로 보면 아래와 같이 볼 수 있다.

그래서 정리해보면 가장 먼저 Worker Thread에서 UI 업데이트 작업 Message를 UI Thread의 Handler에게 전달한다.

Handler는 수신한 Message를 MessageQueue에 삽입한다.

Looper가 MessageQueue에서 Message를 하나씩 꺼내서 Handler에게 전달한다.

Handler는 이 Message를 받아서 UI 업데이트 작업을 하나씩 순차적으로 수행한다.

 

이번 글은 이상으로 마치겠습니다.

감사합니다.

반응형