Nuke Olaf - Log Store

[Android] 안드로이드 - AsyncTask 란? 본문

Android

[Android] 안드로이드 - AsyncTask 란?

NukeOlaf 2019. 12. 30. 17:20

1. AsyncTask 의 사전적 의미

Async : Asynchronous (형용사) - (전자통신) 비동기

- not synchronous; not occuring or existing at the same time or having the same period or phase.

동기식이 아님; 동시에 발생하거나 존재하지 않거나 동일한 기간 또는 단계를 갖는 경우

- pertaining to a transmission technique that does not require a common clock between the communicating devices; timing signals are derived from special characters in the data stream itself.

통신장치들 사이에 공통 클록을 필요로 하지 않는 전송 기술에 관한 것; 타이밍 신호는 데이터 스트림 자체의 특수문자에서 파생된다.

https://www.vocabulary.com/dictionary/asynchronous

task : (특히 힘든, 하기 싫은) 일, 과업, 과제

무슨 말인지는 잘 와닿지 않아서 모르겠지만, 일단 동시에 발생할 수 있는 그런 task(일, 업무) 그런 의미인 것 같다.

 


2. AsyncTask , IT 사전에서의 의미

" AsyncTask enables proper and easy use of the UI thread. This class allows you 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 Executor, ThreadPoolExecutor and FutureTask. "

" AsyncTask를 사용하면 UI 스레드를 적절하고 쉽게 사용할 수 있습니다. 이 클래스를 사용하면 스레드 및 / 또는 핸들러를 조작하지 않고도 백그라운드 작업을 수행하고 UI 스레드에 결과를 게시 할 수 있습니다.

AsyncTask는 Thread and Handler에 대한 도우미 클래스로 설계되었으며 일반적인 스레딩 프레임 워크를 구성하지 않습니다. AsyncTasks는 짧은 작업 (최대 몇 초)에 이상적으로 사용되어야합니다. 스레드를 장기간 계속 실행해야하는 경우 java.util.concurrent 패키지에서 제공하는 다양한 API 를 사용하기를 권장합니다. (예 : Executor, ThreadPoolExecutor, FutureTask. "

https://developer.android.com/reference/android/os/AsyncTask

https://developer.android.com/guide/components/processes-and-threads.html

 

" Android defines AsyncTask as “a class that extends the Object class to allow short operations to run asynchronously in the background.” With “doInBackground” and “onPostExecute,” Async can run tasks asynchronously on new threads. "

" Android는 AsyncTask를 "백그라운드에서 짧은 작업을 비동기 적으로 실행할 수 있도록 Object 클래스를 확장하는 클래스"로 정의합니다. "doInBackground"및 "onPostExecute"를 사용하여 Async는 새 스레드에서 작업을 비동기 적으로 실행할 수 있습니다. "

https://www.upwork.com/hiring/mobile/why-you-should-use-asynctask-in-android-development/

 

" AsyncTask is an abstract Android class which helps the Android applications to handle the Main UI thread in efficient way. AsyncTask class allows us to perform long lasting tasks/background operations and show the result on the UI thread without affecting the main thread. "

" AsyncTask는 Android 애플리케이션이 기본 UI 스레드를 효율적으로 처리하는 데 도움이되는 추상 Android 클래스입니다. AsyncTask 클래스를 사용하면 오래 지속되는 작업 / 백그라운드 작업을 수행하고 주 스레드에 영향을 미치지 않고 UI 스레드에 결과를 표시 할 수 있습니다. "

http://programmerguru.com/android-tutorial/what-is-asynctask-in-android/

 


3. AsyncTask 란?

AsyncTask 가 무엇인지 이해하기 위해서는 우선, 동기와 비동기라는 개념에 대해 숙지해야 한다. AsyncTask 에서 Async 는 "비동기"라는 의미를 갖고 있기 때문이다.

동기(sync)적으로 태스크를 실행한 후 다른 태스크를 실행하기 위해서는, 먼저 실행된 태스크가 종료될때까지 기다려야 한다. 그러나 비동기(async)적으로 태스크를 실행하면, 먼저 실행된 태스크가 종료되지 않아도 다른 태스크를 실행할 수 있다. 이것은 화장실을 예로 들어 생각해 볼 수 있다. 공중 화장실에 사람이 아무리 많이 몰려있는 상황을 상상해보자. 밖에서 줄서서 기다리고 있는 사람들은 화장실 칸에 볼일을 보러 들어간 사람이 나올때까지, 그리고 자신의 차례가 될 때까지 자신의 일을 해결할 수 없다. 그러나, 노상방뇨를 생각해보자. 벽에다가 노상방뇨를 하는 사람을 보고 자신도 노상방뇨가 하고 싶어진 사람은, 옆에서 노상방뇨를 하는 사람의 볼일이 끝날때까지 기다리지 않는다. 옆에서 동시에 노상방뇨를 하면 된다. 정말 웃기고 이상한 예시이긴 하지만 여기서, 공중 화장실이 동기적으로 태스크를 실행하는 것이고, 노상방뇨가 비동기식으로 태스크를 실행하는 것이라고 이해하자.

앱이 실행되면, 안드로이드 시스템은 메인 스레드를 생성한다. 이 스레드는 안드로이드 UI ToolKit 에 접근하여 사용자의 입력을 기다리거나 디바이스 화면에 UI 를 그리는 작업을 한다. 이러한 작업은 메인 스레드에서만 동기적으로 진행되는데, 이때문에 메인 스레드를 UI 스레드라고 부르기도 한다. UI 스레드의 명령은 한 줄씩 실행되기 때문에, 현재 수행중인 코드가 끝나야지 다음 코드가 실행된다. 특별히 다른 worker 스레드를 생성하여 사용하지 않는 한, 앱의 모든 컴포넌트들(Activity, Service, Content Provider, BroadcastReceiver 등)은 같은 메인 스레드 내에서 실행된다. 안드로이드는 단일 스레드 기반 모델(Single Thread model)이기 때문이다.

그런데, 안드로이드가 단일 스레드 기반 모델인 점 때문에 생길 수 있는 문제점이 있다. 바로 UI 와 관련된 작업들도, 시간이 오래걸리는 작업들도 모두 메인 스레드에서 실행하게 된다면, 시간이 오래 걸리는 작업때문에 UI 가 빠르게 그려지지 못하는 상황이 발생할 수 있다는 것이다. 이것을 "반응성이 좋지 않다"라고도 말한다. 이러한 반응성이 좋지 않은 앱은 사용자에게 불편함을 느끼게 할 수 있으며, 5초 이상 UI 스레드가 보여지지 않으면 ANR(Application Not Responding) 오류 (어플리케이션이 응답하지 않습니다 다이얼로그) 가 뜨기 때문에 사용자 경험과 앱의 반응성을 향상시킬 수 있도록 앱을 설계해야한다.

UI 반응성 향상을 위해서는 처리 시간이 오래 걸리는 작업처리를 별도로 해주는 스레드를 사용해주어야 한다. 처리 시간이 오래 걸리는 작업의 예시는 대략적으로 아래와 같다.

  • 인터넷에서 리소스 (mp3, JSON, 이미지 등)에 접근하는 작업
  • 데이터베이스 작업
  • 웹 서비스 호출
  • 오랜 시간이 걸리는 복잡한 논리 작업

이러한 시간이 오래 걸리는 작업처리를 위해 안드로이드에서는 Handler, Runnable, AsyncTask 등을 제공하는 것이다.

AsyncTask 는 메인 스레드에서 생성 후 실행되며, 메인 스레드에서 처리시간이 오래 걸리는 작업을 백그라운드 스레드로 넘기고 메인스레드 작업을 계속 진행하기 위해 사용된다. 백그라운드 스레드는 작업 처리 중에 메인 스레드에서 처리하는 UI 작업에 영향을 주지 않는다. 그래서 UI 가 늦게 뜨거나 터치에 늦게 반응하는 일을 차단할 수 있다.

AsyncTask 를 쉽게 이해하기 위해 들 수 있는 예시로는 측면도로가 있다. 시속 30km (너무 느린것 같지만 극단적인 예를 들기 위해 이렇게 설정했다) 가 최대속도인 엄청 무겁고 큰 트럭(오래 걸리는 작업)이 있다고 생각해보자. 심지어 이 무겁고 느리고 큰 트럭이 1차선 도로(메인 스레드)를 달린다고 생각해보자. 선택의 여지없이 1차선 도로를 30km 속도로 달려야 하는 트럭 때문에(안드로이드는 단일 스레드 모델이다) 다른 차량들(UI 작업)은 추월도 못하고(1차선이라서) 트럭 뒤에서 클락션만 울려야 할 것이다. 이러한 교통문제를 해결하기 위해 교통당국(안드로이드)에서는 트럭을 위한 측면도로(Async Task)를 제공해 준다. 트럭은 측면도로를 타고 제 갈 길을 가다가(오래 걸리는 작업 수행) 필요한 시점에 다시 1차선 도로로 들어오면 된다(수행한 작업 결과를 메인스레드에 전달). 이렇게 측면도로를 이용하면 다른차량들은 트럭을 기다릴 필요없이 쌩쌩 달리면 된다(반응성 및 사용자 경험 향상).

Handler 를 이용해서도 AsyncTask 와 같은 기능을 구현할 수 있지만, AsyncTask 를 사용하면 백그라운드 스레드와 메인 스레드간의 커뮤니케이션이 간단해진다. 백그라운드 스레드에서 작업이 종료되면, 결과를 메인 스레드에 통보해줄 수 있고(onPostExecute), 또한 백그라운드 스레드에서 작업 중에도 메인 스레드에게 UI 요청을 쉽게 할 수 있다(onProgressUpdate)

 

https://www.quora.com/What-is-AsyncTask-in-Android

https://webnautes.tistory.com/1082

https://androidride.com/android-asynctask-example-tutorial/

 

 


4. AsyncTask 를 사용하는 이유, AsyncTask 는 언제 사용해야 할까?

Async Task 는 작업시간이 길어서 Main Thread 의 작업을 방해하는 경우에 사용한다.

자세한 내용은 3번에 다 적긴 했지만, 다시 정리해보자면,

 

https://aroundck.tistory.com/30

 

4.1 AsyncTask 와 Handler 의 차이점은 무엇일까?

AsyncTask 와 Handler 의 장단점에 대해 분석하고, 언제 AsyncTask 를 사용할지, 언제 Handler 를 사용할지 생각하는 것도 좋을 것 같다.

AsyncTask 는 Handler 를 사용하지 않고 UI 를 업데이트할 수 있다.

AsyncTask 는 API 16(젤리빈) 미만 버전에서는 메인스레드에서만 만들어지고 동작할 수 있다고 한다. API 16 이상에서는 자유롭게 사용할 수 있다고 함. 만약 다른 worker Thread 에서 메인 쓰레드에 접근하고 싶다면, Handler 와 Looper 를 만들어서 사용해야 한다. 그래고 AsyncTask 는 하나의 객체이므로 재사용이 불가능하며, 구현한 액티비티가 종료되어도 별도의 지시가 없다면 종료되지 않는다.

AsyncTask was written to provide a convenient, easy-to-use way to achieve background processing in Android apps, without worrying too much about the low-level details(threads, message loops etc). It provides callback methods that help to schedule tasks and also to easily update the UI whenever required.

However, it is important to note that when using AsyncTask, a developer is submitting to its limitations, which resulted because of the design decisions that the author of the class took. For e.g. I recently found out that there is a limit to the number of jobs that can be scheduled using AsyncTasks.

Handler is more transparent of the two and probably gives you more freedom; so if you want more control on things you would choose Handler otherwise AsynTask will work just fine.

 

https://stackoverflow.com/questions/2523459/handler-vs-asynctask

 

5. AsyncTask 를 어떻게 사용하는가?

AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)

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");
     }
 }

 

< When an asynchronous task is executed, the task goes through 4 steps: >

  1. onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
  2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
  3. onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
  4. onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

https://developer.android.com/reference/android/os/AsyncTask#the-4-steps

https://developer.android.com/reference/android/os/AsyncTask


1. onPreExecute() : Background 작업 시작전에 UI 작업을 진행 한다.

2. doInBackground() : Background 작업을 진행 한다.

3. onPostExecute() : Background 작업이 끝난 후 UI 작업을 진행 한다.

[onPreExecute()] -> [doInBackground()] -> [onPostExecute()]

  • doInBackground() 함수를 제외한 나머지 4개의 함수는 전부 Main Thread에서 실행되는 함수들입니다. 

AsyncTask를 실행하면 가장 먼저 onPreExecute() 함수가 호출되며 doInBackground() 함수가 호출되기 직전에 호출됩니다. 일반적으로 해당 함수에서는 사용자 UI에 ProgressBar를 표시하여 본격적인 작업 스레드에 들어가기 전에 작업 진행줄을 표시하는 구현이 들어갑니다. doInBackground() 함수는 작업 스레드를 실행하는 함수로 메인 스레드와는 별개로 오래 걸리는 작업을 처리합니다. 

 

  • onProgressUpdate() 함수는 doInBackground() 함수에서 publishProgress() 함수를 호출하면 호출되는 함수로 작업 스레드를 실행하는 도중에 UI 처리를 담당합니다. 일반적으로 작업 진행 정도를 표시하는 용도로 사용됩니다. 

 

  • doInBackground() 실행 도중 작업이 중단되는 경우에 onCancelled() 함수가 실행됩니다. 반대로 정상적으로 처리가 완료되는 경우에는 onPostExecute() 함수가 호출됩니다. 

 

https://itmining.tistory.com/7

https://whereisusb.tistory.com/25

http://theeye.pe.kr/archives/1447

AsyncTask 의 생명주기, 출처 : https://lktprogrammer.tistory.com/165 

 

AsyncTask 의 생명주기, 출처 : https://tigerwoods.tistory.com/28

 

 

 

Comments