반응형
AsyncTask
Added in API level 3
public abstract class AsyncTask extends Object java.lang.Object -> android.os.AsyncTask<Params, Progress, Result>
Intro
UI Thread(Main Thread)
- 어플리케이션의 프로세스를 실행하는 쓰레드
- 화면 구성 담당 : Button, TextView 등의 UI 구성 요소를 생성 및 조작할 때 상호작용하는 쓰레드
- 시간이 오래 걸리는 작업은 UI 쓰레드로부터 분리하여 별도의 쓰레드에서 실행 하는 것이 좋다.(UI쓰레드 지연 및 차단 방지)
- Android UI 도구는 쓰레드로부터 세이프하지 않다. 따라서 UI 쓰레드가 아닌 쓰레드에서는 UI 구성요소를 조작하지 않는다.
AsyncTask
- UI 쓰레드 를 적절하고 쉽게 사용할 수 있도록 해준다.
- thread 나 handler 를 사용하지 않아도 백그라운드 작업 을 수행하고 UI 쓰레드에 결과를 출력 할 수 있다.
- Thread 와 Handler 와 기능이 유사한 Helper class 이고 Generic Threading framework 를 구성하지 않는다.
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework.
- 이상적으로는 짧은 시간에 동작이 수행 되어야한다.
- 만약 긴 시간동안 쓰레드를 돌려야하면
java.util.concurrent
패키지에서 제공되는 다양한 API들을 사용하는 것을 권장한다.(Executor, ThreadPoolExecutor, FutureTask...)
- 만약 긴 시간동안 쓰레드를 돌려야하면
- 비동기 작업(Asynchronous Task)이란 백그라운드 쓰레드 에서 연산하고 UI 쓰레드 에서는 결과가 보여지는 것을 말한다.
- 비동기 작업을 구성하는 것은 다음과 같다.
- 제네릭 타입
- Params
- Progress
- Result
- 수행 단계
- onPreExecute
- doInBackground
- onProgressUpdate
- onPostExecute
- 제네릭 타입
Usage
- AsyncTask 는 반드시 서브 클래스 로 사용되어야한다. (Override 를 꼭 해야함.)
- 예제 코드// AsyncTask 를 사용하기 위해서는 AsyncTask 를 상속받은 서브클래스를 객체로 만들어야한다. private class DownloadFilesTask extends AsyncTask<URL, Integer, Long>{ protected Long doInBackground(URL... urls){ int count = urls.length; long totalSize = 0; for(int i=0; i<count; i++){ totalSize += Downloader.downloadFile(urls[i]); publishProgress((int)((i / (float) count) * 100)); // Escape early if cancel() is called if(isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress){ setProgressPercent(progress[0]); } protected void onPostExecute(Long result){ showDialog("Downloaded " + result + " bytes"); } }// AsyncTask 실행 new DownloadFilesTask().execute(url1, url2, url3);
- 예제 코드만을 보았을 때 추측 해볼 수 있는 것은 다음과 같다.
AsyncTask<URL, Integer, Long>
에서URL
,Integer
,Long
은 위에서 언급되었던 제네릭 타입Params
,Progress
,Result
이다.- 또한 세 개의 제네릭 타입은 각각
doInBackground()
,onProgressUpdate()
,onPostExecute()
의 인자값 타입과 동일하다. - MainThread를 사용하는 MainActivity에서
DownloadFilesTask().execute(url1, url2, url3)
를 실행하면 execute 메소드의 인자값들은doInBackground()
의 인자값으로 넘어가서 각 url 링크에서 다운받은 파일의 크기를 totalSize 에 합한다. 그리고 총 합쳐진 totalSize 값은onPostExecute()
메소드의 인자값으로 넘겨진다. onProgressUpdate()
메소드는 백그라운드에서 수행 중인 작업의 현재 상태를 출력해주는 메소드이다.
- 그럼 이제 진짜 사실 은 무엇인지 보자.
- 예제 코드만을 보았을 때 추측 해볼 수 있는 것은 다음과 같다.
AsyncTask's generic types
- Intro에서 언급된 AsyncTask 의 제네릭 타입은 총 3가지이다.
Params
: AsyncTask 가execute()
될 때 넘겨받는 인자값 의 타입Progress
: 백그라운드에서 작업이 수행되는 동안 발행되는 진행 단위 의 타입Result
: 백그라운드 작업의 결과값 의 타입
- 3개의 제네릭 타입들을 모두 항상 사용하지 않는다. 사용하지 않을 때는
Void
로 타입값을 넣어준다.private class MyAsyncTask extends AsyncTask<Void, Void, Void> {...}
The 4 steps
- 비동기 작업이 수행될 때, 해당 작업은 총 4단계를 거치게 된다.
onPreExecute()
- 비동기 작업이 이루어지기 전에 UI Thread 에서 호출되는 메소드이다.
- 사용자 인터페이스에 Progress bar 를 표시하여 작업을 설정하는 데 사용된다.
doInBackground(Params...)
onPreExecute()
가 끝나면 Background Thread 에서 호출되는 메소드이다.- 긴 시간이 필요한 백그라운드 연산을 수행하기 위해 사용된다.
- 비동기 작업이 시작될 때 받는 인자값들이 전달되는 단계이다.
- 연산의 결과값이 항상 return 되며 해당 값을 마지막 단계로 전달한다.
- 진행 단위를 출력하고자 할 떄
publishProgress(Progress...)
를 사용한다. - 진행 단위 값들은
onProgressUpdate(Progress...)
단계의 UI Thread 에서 출력된다.
onProgressUpdate(Progress)
publishProgress(Progress...)
이후에 UI Thread 에서 호출되는 단계이다.- 백그라운드 연산이 수행되는 동안 사용자 인터페이스에서 어떤 형태로든 진행 상황을 보여주기 위해 사용된다.
onPostExecute(Result)
- 백그라운드 연산이 끝난 후에 UI Thread 에서 호출되는 단계이다.
- 백그라운드 연산의 결과값은
onPostExecute(Result)
의 인자값이 된다.
Cancelling a task
cancel(boolean)
메소드를 호출함으로써 언제든지 작업을 취소할 수 있다.cancel(boolean)
메소드 호출은 이어서 true 를 반환하는isCancelled()
를 호출한다.isCancelled()
메소드가 호출되면doInBackground()
에서onPostExecute()
로 넘어가지 않고onCacelled()
메소드로 넘어간다.- 이러한 취소 작업을 빨리 수행하기 위해서는
doInBackground()
메소드에서 주기적으로isCancelled()
의 반환값을 확인 해줘야한다.
Threading rules
- AsyncTask 클래스는 UI Thread 에서 로드 되어야한다. 이 점은
Build.VERSION_CODES.JELLY_BEAN
에서 자동으로 수행된다. - Task Instance 는 UI Thread 에서 생성 되어야한다.
execute(Params...)
는 UI Thread 에서 호출 되어야한다.onPreExecute()
,onPostExecute(Result)
,doInBackground(Params...)
.onProgressUpdate(Progress...)
를 수동적으로 호출하면 안된다.- AsyncTask 는 한 번만 실행될 수 있다.(두번째 실행이 시도되면 예외가 발생할 것이다.)
참고자료(출처)
-
AsyncTask https://developer.android.com/reference/android/os/AsyncTask#developer-guides https://itmining.tistory.com/7
-
UI Thread https://codetravel.tistory.com/9
반응형
'Android Developer' 카테고리의 다른 글
[번역] Google Play 인디 게임 페스티벌 결선 진출작들을 만나다. (0) | 2020.04.01 |
---|---|
[Android] APK 용량 줄이기 (0) | 2019.10.08 |
[Android] Task 와 Back Stack (0) | 2019.07.15 |
[Android] Log (0) | 2019.07.10 |
[Android] Activity의 LaunchMode (0) | 2019.07.10 |