본문 바로가기
android

AsyncTask 란

by junmong 2020. 3. 9.

첫번째

한국말로 Sync는 동기화, Async는 비동기화 입니다

프로그래밍 관점에서 동기화와 비동기화가 무엇인지는 다루지 않겠습니다

 

UI 환경에서 오래 걸리는 작업을 Sync(동기화)로 수행하게되면 사용자의 UI 이벤트를 그동안에 처리할 수가 없습니다

이와같이 오래 걸리는 작업은 Main이 아닌 다른 Thread에서 작업이 되어야 합니다

 

그럼 Thread 를 쓰지 왜 AsyncTask 를 쓰나요? 라는 질문이 들어오겠죠.

이 부분은 UI Thread 라는 개념을 알아야 합니다.

보통 UI Platform에서 UI에 관련된 작업은 UI Thread에서만 하게 되어 있습니다.

 

Android의 경우는 Main Thread가 UI Thread 가 같은 개념입니다.

그래서 Thread를 처리하던 중에 Main Thread에서 해야 할 일이 있다면.. ( 주로 UI 관련 작업 )

곤란해집니다.

 

이 때는 보통 Android에서 제공하는 Handler 라는 것을 이용하곤 합니다.

하지만 초보자들에게 이 Handler와 Thread를 사용하는 것은 구현하기도 어렵고 이해하기도 어렵습니다.

그래서 만들어 진 것이 바로 AsyncTask 입니다.

 

간단한 공식으로 이야기하면

AsyncTask = Handler + Thread  입니다.

 

이 AsyncTask 가 Handler와 Thread 에 대한 직접적 Operation 없이

 

두가지 효과를 모두 낼 수 있도록 Wrapping 해놓은 class 라고 생각하시면 되겠습니다.

AsyncTask 는 언제 많이 쓰이나

 AsyncTask 는 작업시간이 길어 Main Thread 또는 UI Thread 의 작업을 방해하는 경우에 주로 사용됩니다.

Thread 가 사용되는 경우와 보통은 일맥상통합니다. 

 

그러나 AsyncTask 는 UI Thread에서의 작업도 필요한 경우에 주로 사용될 수 있겠습니다.

 

 

주로 Network 사용, File 저장 및 불러오기, Database query 등이 대표적인 경우입니다.

 

 

어떻게 사용하죠?

 우선 AsyncTask 는 보통 상속하여 사용합니다.

 

 

public class DownloadTask extends AsyncTask< Params, Progress, Result >{

 

   //... 

 

}

 

상속을 하면서 AsyncTask 내부에서 사용할 3가지 parameter type을 정의합니다.

사용하지 않을 경우는 "Void" 로 정의합니다.

 

Params 는 doInBackground에 전달되는 parameter의 type입니다.

Progress 는 onProgressUpdate에 전달되는 parameter의 type입니다..

Result 는 onPostExecute에 전달되는 parameter의 type이면서 이 값은 doInBackground의 return 값입니다.

 

 

예제를 통해 보면 훨씬 쉽겠죠? Android developer 예제를 참조해 봅시다.

 

private class DownloadFilesTask extends AsyncTask< URL, Integer, Long >{

 

protected Long doInBackground( URL... urls ){

 

   // do something

 

}

 

protected void onProgressUpdate( Integer ... progress ){

 

  // do something 

 

 

 

protected void onPostExecute( Long result ){

 

   // do something

 

 

 new DownloadFilesTask().execute( url1, url2, url3 ); 

 

자 이제 구체적 설명 들어갑니다. 위에서 볼 수 있는 3가지 function 이 AsyncTask에서 가장 많이 쓰이는 function들입니다.

 

doInBackground() 는 Main Thread가 아닌 별개의 Thread에서 작업을 합니다.

doInBackground는 AsyncTask.execute( params ) 를 통해서 수행이 되며 

 

이 params 가 doInBackground의 parameter로 전달됩니다.

이 parameter의 type은 AsyncTask를 extends 하면서 정의해준 type 이어야 합니다.

 

onProgressUpdate() 는 doInBackground에서 일처리를 하다가 

 

"중간에" UI Thread에서 처리할 일이 있는 경우에 불립니다.

doInBackground에서 수행되는 내용은 UI Thread에서 작동합니다.

doInBackground에서 명시적으로 publishProgress( progress ) 를 호출해주었을때 수행됩니다.

 

onPostExecute() 는 doInBackground의 처리가 모두 끝나고 해당 function이 return 되었을 때 호출됩니다.

AsyncTask가 취소되거나 예외 발생시에 parameter 로 null 이 들어옵니다.

이 onPostExecute 의 내용은 UIThread에서 수행됩니다.

 

추가적으로 onPreExecute() 가 있습니다. 이 녀석은

doInBackground가 수행되기 전, 즉 AsyncTask.execute() 를 호출했을 때 가장 먼저 수행되는 녀석입니다.

여기서는 보통 AsyncTask 에서 할 일에 대한 초기화 작업을 해주곤 합니다.

onPreExecute() 안의 내용은 UIThread에서 수행됩니다.

 

추가적으로 onCancelled() 가 있습니다. 이 녀석은 강제로 AsyncTask를 취소했을 대 호출됩니다.

 

아주 간단 정리하면 이렇습니다.

 

AsyncTask.execute()  @ Main Thread

 

-> onPreExecute()  @ Main Thread

 

-> doInBackground()  @ Another Thread

 

-> onProgressUpdate()  @ Main Thread. doInBackground에서 publishProgress() 호출시

 

-> onPostExecute()  @ Main Thread. doInBackground() 가 return 되었을 때

 모든 것은 예제를 통해 보는 것이 낫겠죠?

다음 글에서 간단한 예제와 함께 추가설명 해보겠습니다.

 

Summary

- AsyncTask 는 Thread 와 Handler의 사용을 Wrapping 해논 class 입니다.

 

- AsyncTask는 MainThread와 다른 Thread 의 통신이 필요할 때 사용되며 쉽게 사용할 수 있습니다.

 

- AsyncTask는 주로 오래 걸리는 작업, 예를 들면 Network, Database 작업, File I/O 등에 주로 사용됩니다.

 

- AsyncTask의 수행은 execute( params ) 로 시작됩니다.

 

  onPreExecute() 가 Main Thread에서 수행 된 후 이어 doInBackground() 가 다른 Thread에서 수행됩니다.

 

  doInBackground()에서 작업 수행 중  publishProgress() 를 호출하면 onProgressUpdate() 가 Main Thread에서 호출됩니다.

 

  doInBackground() 작업이 끝나면 onPostExecute() 가 Main Thread에서 수행됩니다.

 

- AsyncTask가 중간에 취소되었을 대는 onCancelled 가 호출됩니다.

 

 

References

-  http://developer.android.com/reference/android/os/AsyncTask.html 

 

  Android developers AsyncTask doc. 

 

 http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html 

 

  Android developers Process & Thread Dev Guide.

 

<!------------------------------------------------------------------------------------------------------!>

 

안드로이드는 기존에 자바에서 제공하는 Thread 뿐만아니라

AsyncTask라는 스레드 객체를 제공한다.

안드로이드가 AsyncTask 라는 객체를 왜 만들어 제공할까?

아래의 글은 Android Developer 에서 발췌한 일부 글이다.

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as ExecutorThreadPoolExecutor and FutureTask.

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread.

 

요약하자면, AsyncTask는 백그라운드 스레드 와 UI 스레드를 같이 쓰기 쉽게 설계했으며, 

일반 스레드와 달리, 간단한 작업에 적합하게 만들었다고 설명되어 있다.

백그라운드 스레드와 UI 스레드를 같이 쓰기 쉽다는 말이 무슨 뜻일까?아래의 설명을 보자.안드로이드에서의 일처리는 메인스레드(UI 스레드)가 담당한다. 특히 UI와 관련된( ex) TextView,ImageView )

일처리는 메인스레드만 담당 하게끔 설계를 했다. 그래서 메인스레드를 UI스레드라고도 불린다.

따라서 복잡한 계산은 백그라운드 스레드( 메인 스레드가 아닌 다른 스레드의 총칭)에 맡긴후 

계산된 결과값을 UI스레드에게 일을 시켜야 하는 것이다.

그래서 AysncTask 라는 객체를 만들었고 위에서 설명한 일들을 쉽게 구현 할 수 있도록 메서드를 제공한다.

AsyncTask객체는 abstract로 작성되었다. 따라서, 익명클래스로 사용허던가 위와 같이 상속을 통해서 사용해야 한다.

 

public class MommooAsyncTask extends AsyncTask<String,Void,String>{

 

제네릭 인자3개를 정해야한다. 

 

첫번째 인자는 doInBackground 메서드에 선언하는 가변인수 매개변수의 타입을 정한다.

 

두번째 인자는 onProgressUpdate 메서드에 선언하는 가변인수 매개변수의 타입을 정한다.

 

세번째 인자는 onPostExecute 메서드에 선언하는 매개변수의 타입을 정한다.

 

@Override

protected void onPreExecute() {

 

super.onPreExecute();

 

}

첫번째 메서드다. 해당 메서드는 이름에서 볼 수 있드시,  background스레드를 실행하기전 준비 단계이다.

변수의 초기화나, 네트워크 통신전 셋팅해야할 것들을 위의 메서드 공간에 작성한다. 

 

@Override

protected String doInBackground(String... params) {

 

return result;

 

}

두번째 메서드다. 해당 메서드가 background 스레드로 일처리를 해주는 곳이다.

보통 네트워크, 병행 일처리등을 위 메서드 공간에 작성한다.

중요한건 마찬가지로 스레드 이므로 UI스레드가 어떤 일을 하고 있는지 상관없이

별개의 일을 진행한다는 점이다. 따라서 AysncTask는 비동기적으로 작동한다.

 

@Override

protected void onProgressUpdate(Void... values) {

 

super.onProgressUpdate(values);

 

}

세번째 메서드는 doInBackground 메서드에서 중간중간에 UI스레드 에게 일처리를 맡겨야 하는 상황일때

쓴다. 매개변수로 Void를 받으므로, doInBackground안에 실제인자가 없이,

 publishProgress( ) 메서드를 호출하면 BackgroundThread 중간에 mainThread에게 일을 시킬 수 있다.

 

@Override

protected void onPostExecute(String s) {

 

super.onPostExecute(s);

 

}

 

마지막 메서드다. background Thread가 일을 끝마치고 리턴값으로 result를 넘겨준다.

그 값을 지금 보고 있는 해당 메서드가 매개변수로 받은후 받은 데이터를 토데로

UI스레드에 일처리를 시킬때 쓰는 메서드이다.

보통 UI변경 ( ex) textview.setText("~~") )할때 많이 사용된다. 왜냐면

위에서도 말했다시피 UI변경은 메인스레드가 아닌 다른 스레드에서의 변경은 막았기 때문이다.

위에서 만든 AysncTask를 사용 하는방법은 아래와 같이 하면된다.

MommooAsyncTask asyncTask = new MommooAsyncTask();

asyncTask.execute();

execute의 아규먼트는 doInBackground에서 받는 String... 가변인수이다. 필요시 넣으면 되겠다.

해당 URL은 저번에 작성한 포스팅인데 AsyncTask를 사용하였다. 예시로 보면 될 것이다.

여기까지가 준비한 AysncTask의 내용이다.

직접 Thread와 Handler 를 구현해보고 작성해봤다면,

안드로이드가 제공해주는 AysncTask가 얼마나 편리한지 알 수 있을 것이다.

 

 

 

두번째

AsyncTask는 백그라운드 스레드와 UI 스레드를 같이 쓰기 쉽게 설계,

일반 스레드와 달리 간단한 작업에 적합하게 만들어짐

안드로이드에서의 일처리는 메인스레드(UI스레드)가 담당한다. 특히 UI와 관련된 Ex) TextView,ImageView)

일처리는 메인스레드만 담당 하게끔 설계를 했다 그래서 메인스레드를 UI스레드라고 불린다

따라서 복잡한 계산은 백그라운드 스레드( 메인 스레드가 아닌 다른 스레드의 총칭)에 맡긴후

계산된 결과값을 UI스레드에게 일을 시켜야 하는 것이다.그래서 AysncTask 라는 객체를 만들었고 위에서 설명한 일들을 쉽게 구현 할 수 있도록 메서드를 제공한다 .아래의 AysncTask 예시를 보자.

 

import android.os.AsyncTask;

 

public class MommooAsyncTask extends AsyncTask<String,Void,String>{

 

public String result;

@Override

protected void onPreExecute() {

super.onPreExecute();

}

@Override

protected String doInBackground(String... params) {

return result;

}

 

@Override

protected void onProgressUpdate(Void... values) {

super.onProgressUpdate(values);

}

 

@Override

protected void onPostExecute(String s) {

super.onPostExecute(s);

}

}

 

AsyncTask객체는 abstract로 작성되었다. 따라서, 익명클래스로 사용허던가 위와 같이 상속을 통해서 사용해야 한다.

public class MommooAsyncTask extends AsyncTask<String,Void,String>{

제네릭 인자3개를 정해야한다. 

첫번째 인자는 doInBackground 메서드에 선언하는 가변인수 매개변수의 타입을 정한다.

두번째 인자는 onProgressUpdate 메서드에 선언하는 가변인수 매개변수의 타입을 정한다.

세번째 인자는 onPostExecute 메서드에 선언하는 매개변수의 타입을 정한다.

 

@Override

protected void onPreExecute() {

 

super.onPreExecute();

 

}

첫번째 메서드다. 해당 메서드는 이름에서 볼 수 있드시,  background스레드를 실행하기전 준비 단계이다.

변수의 초기화나, 네트워크 통신전 셋팅해야할 것들을 위의 메서드 공간에 작성한다. 

 

@Override

protected String doInBackground(String... params) {

 

return result;

 

}

두번째 메서드다. 해당 메서드가 background 스레드로 일처리를 해주는 곳이다.

보통 네트워크, 병행 일처리등을 위 메서드 공간에 작성한다.

중요한건 마찬가지로 스레드 이므로 UI스레드가 어떤 일을 하고 있는지 상관없이

별개의 일을 진행한다는 점이다. 따라서 AysncTask는 비동기적으로 작동한다.

 

@Override

protected void onProgressUpdate(Void... values) {

 

super.onProgressUpdate(values);

 

}

세번째 메서드는 doInBackground 메서드에서 중간중간에 UI스레드 에게 일처리를 맡겨야 하는 상황일때

쓴다. 매개변수로 Void를 받으므로, doInBackground안에 실제인자가 없이,

 publishProgress( ) 메서드를 호출하면 BackgroundThread 중간에 mainThread에게 일을 시킬 수 있다.

 

@Override

protected void onPostExecute(String s) {

 

super.onPostExecute(s);

 

}

 

마지막 메서드다. background Thread가 일을 끝마치고 리턴값으로 result를 넘겨준다.

그 값을 지금 보고 있는 해당 메서드가 매개변수로 받은후 받은 데이터를 토데로

UI스레드에 일처리를 시킬때 쓰는 메서드이다.

보통 UI변경 ( ex) textview.setText("~~") )할때 많이 사용된다. 왜냐면

위에서도 말했다시피 UI변경은 메인스레드가 아닌 다른 스레드에서의 변경은 막았기 때문이다.

위에서 만든 AysncTask를 사용 하는방법은 아래와 같이 하면된다.

MommooAsyncTask asyncTask = new MommooAsyncTask();

asyncTask.execute();

 

execute의 아규먼트는 doInBackground에서 받는 String... 가변인수이다. 필요시 넣으면 되겠다.

해당 URL은 저번에 작성한 포스팅인데 AsyncTask를 사용하였다. 예시로 보면 될 것이다.

http://mommoo.tistory.com/5

여기까지가 준비한 AysncTask의 내용이다.

직접 Thread와 Handler 를 구현해보고 작성해봤다면,

안드로이드가 제공해주는 AysncTask가 얼마나 편리한지 알 수 있을 것이다.

 

'android' 카테고리의 다른 글

Android LiveData 알아보기 (feat.ViewModel,Room)  (0) 2020.05.25
Android MVP  (0) 2020.03.10
Room 사용하기  (0) 2020.03.10
안드로이드 서비스 4가지 주요 컴포넌트  (0) 2020.03.06
안드로이드 생명주기  (0) 2020.03.06