AsyncTask 클래스는 안드로이드에서 요구하는 메인 스레드(Main Thread)와 작업 스레드의 분리 구조를 보다 쉽게 구현하도록 도와주는 추상 클래스
안드로이드의 AsyncTask 생명주기 관리는 다섯 가지의 생명주기 함수들을 재정의함으로써 관리할 수 있습니다.
인자는 3 제네릭 타입 으로 정의, Params, Progress, 그리고 Result 이며,
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");
}
}
// -------------------------------------------------------------------------------
new DownloadFilesTask().execute(url1, url2, url3);
가변인자는 0 혹은 그 이상의 인자를 받을 수 있음을 나타낸다.
thisIsFunction(); // 가능
thisIsFunction("arg1"); //가능
thisIsFunction("arg1", "arg2", "arg3"); //가능
thisIsFunction(new String[]{"arg1", "arg2", "arg3"}); //가능
/*
인자를 omit 하여도 성립하고, 1개 이상의 인자를 넘겨주거나,
배열 형태로 넘겨 줄 수 있다. 하지만, 여기서 주의해야 할 점은,
인자를 1개만 넘겨주어도 배열의 형태로 다뤄줘야 한다는 점
*/
// doInBackground 함수로 돌아가서, urls를 1개만 넘겨주었더라도,
protected Long doInBackground(URL... urls) {
long totalSize = Downloader.downloadFile(urls[0]);
return totalSize;
}
/*배열로 처리해주어야만 한다.
또한, varargs를 다른 parameter와 동시에 넘겨줄 경우
varargs는 항상 나중에 자리해야만 한다.
*/
// -------------------------------------------------------------------------------
thisIsFunction(int n, String... strings) // 가능
thisIsFunction(String... strings, int n) // Error
///AsyncTask는 cancel(boolean)을 통해 취소할 수 있다.
downloadTask.cancel(true);
AsyncTask가 취소되면, onPostExecute(Object)가 호출 되지 않고, 대신 onCancelled(Object)가 호출되게 되는데, 시점은 doInBackground(Object[])가 return 될 때이다.
Task가 cancel 되었을 때 최대한 빨리 Task가 cancelled에 대한 처리를 하게 하고 싶다면, isCancelled()를 doInBackground 함수 내에서 주기적으로 체크하게 해야한다.
Android Developers의 공식 문서에는
onPreExecute()
onPostExecute(Result)
doInBackground(Params...)
onProgressUpdate(Progress...)
를 명시적으로 호출하지 말라고 한다.
또한, AsyncTask의 생성과 로드, execute() 함수 호출은 UI thread에서 실행되어야 하며,
task의 실행은 한 번만 호출되어야 한다고 명시하고 있다.