매번 미루던 안드로이드 정리,, 한다 이젠,,
+ Service 정리도 해야한다.
- 안드로이드에서는, Main Thread 를 통해서만 화면 UI 를 변경할 수 있다.
-> 따라서, 핸들러를 통해서 Main Thread 에 접근하여 UI 를 수정할 수 있다.
- 안드로이드에서 반복 작업을 하기 위해서는 핸들러 객체를 써야 하는데,
'반복 작업'을 하는 타이머와 같은 것들을 구현하면서 가볍게 넘겨버린 개념이 확실하지 않아서,,
- 스레드와 핸들러의 개념은 꼭 정리해야 하는 것,,
스레드(Thread) 란?
1. 스레드의 정의
1) 동시에 수행 가능한 작업 단위
- 하나의 프로세스 안에서 동시에 수행되어야 하는 작업을 위해 사용
2) 프로세스 내에서 '순차적으로 실행되는 실행 흐름' 의 최소 단위
- 프로그램의 'main() 함수로부터 시작되는 최초 실행 흐름' = '메인 스레드'
3) 안드로이드 앱에서 메인 스레드
- 안드로이드에서 UI를 처리할 때 사용되는 기본 스레드
Ex) 메시지 큐(Message Queue) 수신을 대기하는 루프 실행
- 사용자 입력과 시스템 이벤트, 화면 그리기 등의 메시지가 수신되면
-> 각 메시지에 매핑된 핸들러의 메서드 실행한다.
2. 스레드의 특징
- 같은 프로세스 안에 들어 있으면서 메모리 리소스를 공유(효율적)
- 동시에 리소스에 접근 시 데드락(DeadLock) 발생 가능 -> 이때, 작업을 순서대로 처리하게 도와주는 핸들러로 해결 가능
- 같은 프로세스 안에서 일련의 기능이 순서대로 실행될 때 : 문제 X
- 대기 시간이 길어지는 네트워크 요청 등의 기능 수행 시 화면에 보이는 UI도 멈추는 상태로 존재하는 문제 발생
-> 서비스 / 멀티 스레드를 통해 해결 가능!
3. 스레드 사용 시기
- 구현하고자 하는 기능이, 메인 스레드와 병행적(Concurrently)으로 실행되어야 할 때 별도의 스레드 작성 필요
Ex) 어떤 기능을 - 메인 스레드에 구현
다른 기능을 구현하고자 할 때, 메인 스레드의 동작에 영향을 주는가?
-> 만약, 다른 기능의 실행 시간이 오래 걸리거나, 외부 데이터를 수신하기 위해 대기 상태에 머물러야 하는 경우
-> 메인 스레드의 동작에 영향을 줄 수 있어, 별드의 스레드 작성 필요
4. 멀티 스레드
(1) 멀티 스레드(Multi Thread) 개념
- '하나의 프로세스 내'에서, '둘 이상의 스레드'가 동시에 작업을 수행하는 것
+ 멀티 프로세스(Multi Process) : 여러 개의 CPU를 사용해 여러 프로세스를 동시에 수행하는 것
- 멀티 프로세스는, 각 프로세스가 독립적인 메모리를 가지고 별도로 실행
멀티 스레드는, 각 스레드가 자신이 속한 프로세스의 메모리를 공유
(2) 멀티 스레드의 장점
- 각 스레드가 자신이 속한 프로세스의 메모리 공유 -> 시스템의 자원 낭비 감소
- 하나의 스레드가 작업할 때 다른 스레드가 별도의 작업 진행 가능 -> 사용자와의 응답성도 좋아짐
(3) 멀티 스레드의 프로그래밍
- 멀티 스레드 프로그래밍에서 고려해야 할 사항이 싱글 스레드 프로그래밍 보다 많아짐
-> 안드로이드의 메인 스레드가 아닌 스레드에서 뷰(View)에 대한 직접적인 접근 시 오류가 발생한다.
-> 기능은 반드시 메인 UI 스레드에서 실행되어야 함
-> 스레드 간 통신 필요
스레드와 스레드 통신(Thread Communication)
- 스레드 통신이란, 하나의 스레드에서 -> 다른 스레드로 데이터를 전달하는 것
1. 스레드의 성질(독십성)
- 모든 스레드는, 기본적으로 '독립적인 실행 흐름' 을 가짐
- 일단, 스레드가 실행되고 나면 -> 다른 스레드로부터 어떠한 간섭도 받지 않고, 다른 스레드가 어떻게 실행되고 있는지 관심을 두지 않는다.
-> 그러나, 이러한 독립성은 스레드의 본질적 특징일 뿐
-> 스레드의 상태나 결과를 -> 다른 스레드로 전달하도록 의도적으로 구현해야 하는 경우가 대부분
2. 스레드 통신 예시
- USB 메모리에 있는 파일을 내부 스토리지로 복사해야 하는 상황
- 파일 크기 = GB 단위인 경우, 복사 완려까지 많은 시간 소요
-> 파일 복사 기능 = 메인 스레드가 아닌, 별도의 스레드를 통해 처리 => 파일 복사 스레드
- Main 화면에서 "COPY" 버튼을 통해 새로운 스레드가 실행되도록 만들기
- 이때, 파일 복사가 얼마나 진행되었는지 진행 상태/결과를 화면에 표시하기 위해 progress bar 를 추가
- 그러나, 위와 같이 메인 화면에 progress bar를 추가하고
-> 파일 복사 스레드에서 진행상황을 progress bar에 나타내기 위해 setProgress()로 접근하게 되면 에러가 발생
"Only the original thread that created a view hierarchy can touch its views."
-> 에러 원인 : 안드로이드에서, '화면 UI 뷰 접근'은 반드시 '메인 스레드' 에서 실행되어야 함!!
-> 아래와 같이 파일 복사 스레드의 진행 상태를 메인 스레드로 "메시지 형태"로 전달
-> 메인 스레드에서는 이 메시지 값을 사용해 현재 진행 상태를 화면에 표시
안드로이드 스레드 통신 - 핸들러(Handler)
- 안드로이드에서 사용 가능한 스레드 통신 방법 중 가장 일반적인 방법 : 핸들러를 통한 메시지 전달
- Thread : 프로세스 내의 세부 작업 단위
- Handler
- Message, Runnable Task를 Message Queue 로 전달
- Message, Runnable Task를 실행
- Looper : Message Queue 에서 Handler 로 전달
- Message Queue : Message, Runnable Task 를 저장하는 Queue
1. 메시지(Message, android.os.Message)
(1) 메시지의 개념
1) 스레드 통신에서, 핸들러를 사용해 데이터를 보내기 위해 데이터를 한 곳에 저장하는 역할을 하는 클래스
2) 데이터 종류를 식별하는 식별자,
실질적인 데이터를 저장한 객체,
추가 정보를 전달할 객체
3) 하나의 데이터를 보내기 위해 한 개의 Message 인스턴스 필요
-> 데이터를 담은 Message 객체를 핸들러로 보내면
-> 해당 Message 객체는 핸들러와 연결된 메시지 큐에 쌓임
2. 메시지 큐(MessageQueue, android.os.MessageQueue)
(1) 메시지 큐의 개념
1) Message 객체를 큐(Queue) 형태로 관리하는 자료 구조
2) FIFO(First In First Out)_ 방식으로 동작
-> 메시지는 큐에 들어온 순서대로 차례대로 저장 (First In)
-> 가장 먼저 들어온 Message 객체부터 순서대로 처리(First Out)
(2) 안드로이드에서 메시지 큐
1) MessageQueue 클래스에 구현
2) 앱의 Main Thread 에서 기본적으로 사용
3) 개발자가 Message 객체를 직접 참조해 메시지를 전달하거나, 메시지를 가져와서 처리 X
-> 메시지 전달 = 메시지 큐에 연결된 핸들러(Handler)를 통해
-> 메시지 큐로부터 메시지를 꺼내고 처리 = 루퍼(Looper) 가 수행
3. 루퍼(Lopper, android.os.Looper)
(1) 루퍼의 역할
1) MessageQueue = Message 객체 리스트를 관리하는 클래스
-> 큐에 쌓인 메시지 처리를 위한 핸들러 실행 X
-> 메시지 큐로부터 메시지를 꺼내오고 -> 해당 메시지와 연결된 핸들러 호출하는 역할 수행
2) 메시지 처리를 위한 메시지 루프(Message Loop) 실행
(2) 안드로이드에서의 Looper
1) Main Thread 에는 Looper 객체를 사용해 메시지 루프를 실행하는 코드 구현 O
- 해당 루프 안에서 메시지 큐의 메시지를 꺼내어 처리하도록 만들어짐
-> 메인 스레드에서 메시지 루프와 관련된 코드 추가 작성 필요 X
2) 메인 스레드로 전달할 Message 객체 구성 -> 스레드의 메시지 큐에 연결된 핸들러를 통해 해당 메시지 보내기
4. 핸들러(Handler, android.os.Handler)
(1) 핸들러의 역할
- 스레드의 루퍼(Looper)와 연결된 메시지 큐로 메시지를 보내고, 처리할 수 있도록 함
- Main Thread의 메시지 처리 흐름에서 - 메시지 전달/처리를 위해 개발자가 접근 가능한 창구 역할 수행
(2) 핸들러 구현
- 스레드와 관련된 핸들러를 얻기 위해 : new 키워드를 통해 Handler 클래스 인스턴스 생성
-> 새로운 Handler 인스턴스는, 자동으로 해당 스레드와 메시지 큐에 연결(bound)
-> 이 시점부터, 핸들러를 통해 메시지 전달 및 처리 가능
이 다음은, 핸들러(Handler)를 사용해 스레드 통신을 구현하는 방식, 핸들러가 제공하는 추가 기능에 대해,,
참고
'Mobile > Android' 카테고리의 다른 글
[Android] 안드로이드 Activity 생명주기(Life Cycle) (0) | 2022.04.08 |
---|---|
[Android] 안드로이드 Fragment 생명주기 (0) | 2022.04.08 |
[Android] 안드로이드 브로드캐스트 리시버(Broadcast Receiver) 예제 (0) | 2022.04.04 |
[Android] 안드로이드 4대 컴포넌트 (0) | 2022.04.04 |
[Android] 안드로이드 핸들러(Handler) (0) | 2022.04.01 |