Efficient Android Threading #8 AsyncTask 로 백그라운드 태스크를 UI 스레드에 묶기
이 글은 Efficient Android Threading 의 일부 내용만 발췌한 내용입니다.
자세한 내용은 책을 구입해서 보세용.
10.1. 기본 사항
-
AsyncTask 는 실행이 완료되면 다시 실행할 수 없다.
즉, execute 메서드는 일회성의 동작이고 스레드의 동작처럼 AsyncTask 인스턴스마다 오직 한 번만 호출할 수 있다.
-
doInBackground 작업이 끝나면 onPostExecute 혹은 onCancelled 둘 중 하나만 수행된다.
** 10.1.1 생성과 시작
-
AsyncTask 의 기본 생성자는 UI 스레드에서 호출되어야 한다.
젤리빈 이전의 플랫폼에서 UI 스레드가 아닌 다른 스레드가 AsyncTask 를 생성하면 콜백은 올바른 스레드에서 일어나지 않을 수 있다.
AsyncTask 를 생성한 스레드에 따라 onProgressUpdate, onPostExecute, onCancelled 콜백이 어떤 스레드에서 실행될지 결정된다.
실제로 앱 프로세스에서 첫 번째로 생성된 AsyncTask 는 앱 내의 연이은 모든 AsyncTask 구현에 대한 콜백 스레드를 제어한다.
콜백 스레드는 앱 수명마다 한 번만 설정된다.
젤리빈부터 AsyncTask 는 UI 스레드에서 앱 시작 시 클래스 로드되어 콜백이 UI 스레드에서 일어남을 보장한다.
-
execute 메서드는 UI 스레드에서 호출해야 한다. 그렇지 않으면 onPreExecute 콜백이 UI 스레드에서 일어나지 않는다.
-
실행은 한 번만 호출되는 일회성 테스크이며, 두 번 이상 호출하면 IllegalStateException 이 발생한다.
** 10.1.2. 취소
-
AsyncTask.cancel(true) 에서 boolean flag 값은 isCancelled flag 만 켤 것이냐, interrupt 도 걸 것이냐를 결정한다.
true 이면 interrupt 까지 건다.
** 10.1.3. 상태
-
AsyncTask.getStatus() 를 통해 얻는다.
PENDING
AsyncTask 인스턴스가 생성되었지만, execute 가 호출되지 않음.
RUNNING
execute 가 호출되었음, onPostExecute, onCancelled 함수 처리가 끝날 때까지 이 상태임
FINISHED
onPostExecute 또는 onCancelled 메소드 처리가 다 끝난 상태.
10.2. AsyncTask 구현
** 10.2.1. 예제 : 이미지 다운로드
10.3. 백그라운드 태스크 실행
-
AsyncTask.execute(Runnable) 함수도 있는데, 이 녀석은 API 11 에서 추가되었으며, AsyncTask 내부 실행 환경에서 처리되지만, 스레드 간의 통신을 위해 메시지 전달을 사용하지 않는다.
onPreExecute, onPostExecute, onCancelled 는 호출되지 않고 진행 상태도 표시되지 않는다.
-
asyncTask.executeOnExecutor 역시 API 11 에서 추가되었으며, 이 메서드는 내부 실행 환경을 활용하거나 커스텀 Executor 를 사용한다.
Executor 인수는 다음 중 하나가 될 수 있다.
AsyncTask.THREAD_POOL_EXECUTOR
테스크들이 동시 처리된다. 킷캣에서 스레드 풀 크기는 사용 가능한 CPU 코어 수에 기초한다.
N+1 개의 코어 스레드와 최대 2*N + 1 개의 스레드, 작업 큐는 128개의 태스크를 보유할 수 있다.
AsyncTask.SERIAL_EXECUTOR
스레드 안전한 테스크 실행을 보장한다.
자신의 스레드를 포함하지 않고, 대신 실행을 위해 THREAD_POOL_EXECUTOR 에 의지한다.
무제한 큐에 태스크를 저장하고 순차적으로 실행되도록 각 태스크를 THREAD_POOL_EXECUTOR 로 전달한다.
즉 태스크들은 스레드 풀의 각기 다른 스레드에서 실행될 수 있지만, 순차적 실행은 보장한다.
커스텀 executor 도 설정 가능하다.
-
AsyncTask 는 UI 스레드에 덜 방해되도록 Process.THREAD_PRIORITY_BACKGROUND 로 낮춰진다.
** 10.3.1. 앱 전역 실행
-
모든 AsyncTask 인스턴스는 전역 실행을 공유하기 때문에 실행 환경에 따라 인스턴스끼리 서로 영향을 줄 수 있다.
SERIAL_EXECUTOR
API Level 13 이상의 execute 에서는 기본이 SERIAL 이다.
THREAD_POOL_EXECUTOR
API Level 13 이전의 execute 에서의 기본 동작이었다. ( 3 이하는 순차였지만 무시.. )
이 동작은 targetSdkVersion 의 버전에 의존한다.
** 10.3.2. 다양한 플랫폼 버전에서 실행
** 10.3.3. 커스텀 실행
10.4. AsyncTask 의 대안
** 10.4.1. AsyncTask 가 너무 평범하게 구현된 경우
-
doInBackground 만 구현한 경우에는 Thread 나 HandlerThread 를 사용하는 것이 좋다.
** 10.4.2. 루퍼가 필요한 백그라운드 태스크
** 10.4.3. 지역 서비스
-
서비스는 다음 중 하나의 대안 해결책을 사용하는 것이 좋다.
Thread, Executor Framework, HandlerThread, 커스텀 실행자를 가진 AsyncTask
** 10.4.4. execute(Runnable) 사용
-
장점 : 이미 존재하는 AsyncTask 내부 스레드 풀에서 태스크가 실행되므로 자원 효율적이다.
단점 : 태스크는 항상 앱 전역 실행 환경에서 실행하고 다른 태스크를 방해할 수 있다.
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
Efficient Android Threading #10 인텐트 서비스 (0) | 2018.03.26 |
---|---|
Efficient Android Threading #9 서비스 (0) | 2018.03.25 |
Efficient Android Threading #7 Executor 프레임워크를 통한 스레드 실행 제어 (0) | 2018.03.23 |
Efficient Android Threading #6 핸들러 스레드 : 고수준 큐 메커니즘 (0) | 2018.03.22 |
Efficient Android Threading #5 기본 스레드의 생명주기 관리 (0) | 2018.03.21 |
댓글