안드로이드

[스크랩] 스레드 - 핸들러 - 루퍼(Looper)

start1a 2020. 1. 12. 20:47

https://itmining.tistory.com/5

 

[안드로이드] Thread, Handler, Looper를 통한 백그라운드 처리

이 글은 PC 버전 TISTORY에 최적화 되어있습니다. 서론 안드로이드의 UI는 기본적으로 메인스레드를 주축으로하는 싱글 스레드 모델로 동작하므로, 메인 스레드에서는 긴 작업을 피해야 합니다. 즉 긴 작업은 여분..

itmining.tistory.com

 

안드로이드 UI

  • 기본적으로 메인 스레드를 중심으로 하는 싱글 스레드 모델
  • 긴 작업은 다른 곳에서 하고 메인 스레드와 같은 UI 스레드에서는 UI 변경만 담당하도록 스레드 간의 통신 유도

핸들러 (Handler)

  • Message나 Runnable 객체를 받아 다른 곳으로 전달함
  • 이미지를 받아 UI에 표시할 때, AsyncTask와 더불어 사용

 

Handler와 Looper를 사용하는 이유

 

 

두 스레드를 병렬 처리할 때 동기화 문제 발생

두 스레드에서 병렬 처리로 UI를 변경할 때 동기화 문제 해결을 위해 안드로이드에서는 메인 스레드에서만 UI 작업이 가능하도록 제한하고 있기 때문이다. Sub Thread에서 UI 작업 시 Handler와 Looper를 이용해 Main Thread로 작업할 메시지를 전달하거나 Main Thread 내에서 자체적으로 처리하여야 한다.

 

 

Handler와 Looper의 동작 과정

Handler의 처리 방법

  • Runnable 메시지는 run() 메서드를 통해 처리
    • Thread(Runnable runnable) 생성자로 Runnable 인터페이스를 구현한 개체를 생성
    • 이 개체를 상속받은 스레드는 추상 메서드 run()을 반드시 구현해야 함
  • Message는 handleMessage() 메서드를 통해 처리
  1. 메시지는 다른 스레드에 속한 Message Queue에 전달됨
  2. Message Queue에 메시지를 넣을 땐 Handler의 sendMessage()를 이용함
  3. Looper는 Message Queue에서 Loop()를 통해 반복적으로 처리할 메시지를 Handler에 전달함
  4. Handler는 handleMessage()를 통해 메시지를 처리함

Looper

  • 하나의 스레드만 담당할 수 있음. 스레드도 하나의 Looper만 가짐
  • Message Queue가 비었으면 대기하고 메시지가 들어오면 메시지를 꺼내 적절한 Handler로 전달
  • 이 행동을 반복적으로 수행하므로 Looper라고 함

 

Looper 생성 방법 2가지

1.

1
2
3
4
5
6
7
8
9
Thread t = new Thread(new Runnable(){
    @Override
    public void run() {
        Looper.prepare();
        handler = new Handler();
        Looper.loop();
    }
});
t.start();
 

 

 

  • 특정 스레드 내부에서 Looper.prepare() : Message Queue 준비
  • handler = new Handler() : 원하는 핸들러 생성
  • Looper.loop() : 메시지 전달을 기다리는 작업 시작
  • Activity onDestory() 시 handler.getLooper().quit()를 사용해 반드시 종료할 것!

 

2.

HandlerThread t = new HandlerThread("My Handler Thread");
t.start();
handler = new Handler(t.getLooper());

 

  • 안드로이드에서 제공하는 HandlerThread 클래스 활용
  • HandlerThread 클래스가 내부에 기본적으로 Looper를 가짐
  • 해당 스레드 start하면 자동으로 Loop도 실행되어 매우 편리

 

 

Handler 단독 사용

  • Handler를 Looper 없이 사용하는 경우가 많음
  • 안드로이드에서 편의성을 제공하기 위해 Handler의 기본 생성자로 생성 시 단독 사용 가능
    • Handler를 생성한 스레드의 Message Queue와 Looper에 자동 연결됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class MainActivity extends AppCompatActivity {
 
Handler mHandler = null;
 
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new Handler();
 
Thread t = new Thread(new Runnable(){
            @Override
            public void run() {
                // UI 작업 수행 X
                mHandler.post(new Runnable(){
                    @Override
                    public void run() {
                        // UI 작업 수행 O
                    }
                });
            }
        });
        t.start();
   }
 

 

 

  • 메인 스레드에서 Handler 생성
  • 해당 Handler는 호출한 스레드(메인 스레드)의 Message Queue, Looper가 자동 연결됨
  • 다른 스레드에서 Handler를 통해 메시지 전달 -> 메인 스레드에서 UI 작업 가능