- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 28 |
29 | 30 | 31 |
- Kotlin
- Higher-Order
- bitmasking
- 알고리즘
- 백준
- 탐탁노트북파우치
- 등산로조성
- nullalble
- MVVM
- 아키텍처패턴
- 안드로이드
- tomtoc
- 삼성청년sw아카데미
- 싸피
- DataBinding
- 탐탁삼성파우치
- Android
- Java
- 코딩테스트
- #충무로맛집#골목식당#스테이크#
- 비트마스킹
- 코틀린
- 자바
- 안드로이드#코틀린#디자인패턴#싱글턴패턴#개발#앱개발
- 삼성역량테스트
- kotiln
- 삼성파우치
- ssafy서울
- lateinit
- 투포인터
공상하는 개발자
[기초 탄탄] 안드로이드 스레드 파헤치기. 본문
뭔가 안드로이드 개발을 하면서..
지식들이 정리가 안되는 느낌이 들었다..
그래서 기초탄탄 시리즈 제작을 하게 되었다.(언제까지 할진 모름 ㅎ)
열심히 해보자.
첫 주제는 스레드~고고!!
★ 스레드란?
-> 스레드는 순차적으로 실행되는 실행 흐름 의 최소 단위를 말한다. 프로그램에서 main() 으로 부터 시작되는 최초 실행 흐름도 하나의 스레드이며, 이를 메인 스레드라고 부른다.
1. 안드로이드 시작점은 어디?
-> 메인스레드는 최초로 실행되는 스레드를 지칭한다. 안드로이드에서는 main() 함수를 따로 구현할 필요가 없어서 시작점이 어디인지 잘 모를 수 있다. 앱에서는 최초로 실행시키는 액티비티가 존재한다. 그러한 액티비티를 런처로 지정함으로써, 이 액티비티를 시작점으로 만든다. 그렇다고 앱이 실행될 때 아무런 준비 과정 없이, 무작정 런처로 지정된 액티비티가 실행되는 것은 아니다. main()함수는 안드로이드 프레임워크에 존재하며, 앱 동작에 필요한 여러 준비 동작을 수행해주는데, 그 중에 메인 UI 스레드 실행이 가장 중요하다. 이 과정 이후 런처로 지정된 액티비티를 실행해준다.
2. 안드로이드 메인 UI 스레드
2.1 메시지 큐
-> 보통의 액티비티의 경우 클릭이벤트가 있는 등 사용자 입력이 필요한 프로그램이 대부분이다. 선형적으로 실행하고 끝나는 과정에서는
이러한 입력을 처리할 수 가 없다. 이를 위해 루프(Loop)가 자체적으로 실행이 된다. 이 루프는 단순히 for문,while문이 아니다. UI 프레임워크는 메시지 큐를 사용하여 루프의 코드를 작성하도록 가이드한다. 메시지 큐란 Queue 자료구조의 성격을 가진다. 만약 클릭리스너 A,B가 있다고 치자. A와 B가 메시지큐에 들어가게 되고, 액티비티에서 만약 클릭리스너 A가 수신되면, 그에 맞는 A핸들러(function())를 실행시켜준다. (정확한 개념은 아닌거같지만 이런느낌으로 이해를 하자..)
2.2 화면 그리기 역할
-> 결론부터 말하자면 그리기 기능은 반드시 UI 스레드에서만 실행되어야만 한다. 이유를 설명해보겠다. 예를 들어 바탕에 색을 칠하는 스레드 A, 버튼을 그리는 스레드 B, 이미지를 그리는 스레드 C가 있다고 가정하자. 정상적으로 보이려면 A->C->B 순서로 실행되어야 한다. 하지만 스레드를 실행시켜서 UI를 그린다고 했을 때 스레드의 속도는 경우에 따라서 달라진다. 만약 버튼이 되게 작아서 버튼을 먼저 그리고 바탕을 그리게 되면 바탕에 묻혀서 버튼은 안보이게 될것이다. 그래서 요소를 그리는 순서가 중요하기 때문에 메인 UI 스레드 하나에서 순차적으로 그리도록 만들어야 한다.
3. 멀티 스레드
3.1 어떠한 경우에 스레드를 사용하는가?
-> 구현하고자 하는 기능이 메인 스레드와 병행적으로 실행되야하는지 확인한다. 실행시간이 오래 걸린다거나, 외부 데이터를 수신하기 위해 대기상태에 머물러야 할때는, 메인스레드의 동작에 영향을 줄수 있기에 별도의 스레드로 작성해야한다. 하지만 이 과정은 스레드를 하나 돌리는것보다 당연히 어려운 점이 많다. 이를 멀티스레드라고 부른다. 두개 이상의 스레드를 동시에 실행해야하니까 복잡해지기 마련이다. 안드로이드 개발 에서는 몇가지 이슈들만 파악해도 멀티스레드 프로그래밍을 할 수 있다.
3.2 스레드 간의 통신
-> 만약 USB 의 파일을 내부 저장장소로 복사해야한다고 가정하자. 파일의 크기가 기가바이트일 경우, 복사 완료까지 많은 시간이 걸리므로메인스레드에서 실행하게 되면 일정시간동안 파일 복사때문에 프로그램이 멈출수가 있다. 그래서 별도의 스레드를 통해 처리하기로 결정했다. 별도의 스레드에 복사 기능을 구현하고 프로그레스바를 통해 진행상황을 보여주려하였지만 별도 스레드에서 UI 에 접근하고 있기에 에러가 뜨게된다. 그래서 별도스레드의 진행상황을 메시지로 메인스레드에 전달하여 프로그레스바에 띄워주려고 한다. 그럴때 스레드간 통신에 필요한 핸들러를 사용하게 된다.
4. 핸들러(Handler)
4.1 메시지.
-> 스레드 통신에서 핸들러를 사용하여 데이터를 내보내기 위해서는, 객체가 필요하다. 전달할 데이터를 저장할 클래스가 바로 메시지 클래스이다. 하나의 데이터를 보내려면 한개의 메시지 인스턴스가 필요하며, 데이터를 담은 메시지 객체를 핸들러로 보내면 해당 객체는 핸들러와 연결된 메시지큐에 쌓이게 된다.
4.2 메시지 큐
-> 메시시 객체를 큐 형태로 관리하는 자료구조를 말한다. 큐의 자료구조를 가져서 가장 먼저 들어온 메시지 객체부터 순서대로 처리된다. 개발자가 직접 메시지큐 객체를 직접 참조하여 메시지를 전달하거나, 메시지를 가져와서 처리하지는 않습니다. 메시지 전달은 메시지 큐에 연결된 핸들러를 통해서하고 메시지큐로부터 메시지를 꺼내고 처리하는 역할은 Looper가 수행하기 떄문이다.
4.3 루퍼
-> 메시지큐는 메시지 객체 리스트를 관리하는 클래스일 뿐, 큐에 쌓인 메시지 처리를 위한 핸들러를 실행시키지는 않는다. 메시지 큐로부터 메시지를 꺼내온다음, 해당 메시지와 연결된 핸들러를 호출하는 역할은 루퍼가 한다.
4.4 핸들러
-> 핸들러는 스레드의 루퍼와 연결된 메시지 큐로 메시지를 보내고 처리할 수 있게 만들어준다. 메시지 전달과 처리를 위한 다리역할을 한다고 보면 된다.
매번 한 번 읽고 돌아서면 까먹었던 핸들러와 스레드...
이번 기회로 제대로 이해할 수 있어서 좋았고
더이상 까먹지 않겠다!!
참고자료
https://recipes4dev.tistory.com/166
'개발 > 안드로이드' 카테고리의 다른 글
[안드로이드] 서버에 form data 로 데이터 전송하기.(MultiPart) (4) | 2020.07.14 |
---|---|
[아키텍쳐 패턴] 3탄 : MVVM 패턴 적용하기. (1) | 2020.04.19 |
[Android/kotlin] DataBinding 파헤치기 (0) | 2020.02.09 |
[Kotlin] Higher-Order Functions 이란? (0) | 2020.02.02 |
[Kotlin] Null 안정성 파헤치기 (0) | 2020.01.25 |