시리즈

7.1: AsyncTask and AsyncTaskLoader(1 AsyncTask)

20171120
android
daily

https://google-developer-training.gitbooks.io/android-developer-fundamentals-course-concepts/content/en/Unit%203/71c_asynctask_and_asynctaskloader_md.html
(Android Developer Fundamentals Course 7.1)

Contents:
안드로이드에서 백그라운드 작업을 하는 방법은 2가지가 있습니다.
  1. AsyncTask 클래스를 이용하는 법
  2. Loader 프레임워크를 이용하는 법

대부분의 상황에서 Loader 프레임워크를 이용하게 된다.
그러나 AsyncTask 클래스가 어떻게 동작하는 지를 알아두어야 둘 중 필요한 것을 상황에 맞게 선택할 수 있다.

The UI thread
- UI thread는 적절한 UI 위젯에 이벤트를 전달하는 역할
- 앱이 Android UI 툴킷의 구성요소와 상호작용하는 곳

<중요한 2가지 규칙>
1. UI 스레드를 차단하면 안된다.
2. UI 작업은 UI 스레드에서만 해야한다.

UI 스레드를 5초 이상 차단하면 응답하지 않는 프로그램으로 처리되어 종료될 수 있다.
--> ui 화면에 대해서 16ms 미만으로 작업을 처리한다. // 오래 걸리는 작업은 백그라운드에서 처리한다.
UI를 조작하기 위해서 백그라운드 스레드를 사용하면 안된다. (스레드-안전하지 않음)

AsyncTask 클래스

비동기적, 시간이 오래걸리는 작업을 worker 스레드에서 구현할 때 AsyncTask 클래스를 사용한다. (worker 스레드는 메인이나 UI 스레드가 아닌 스레드를 말한다.) AsyncTask는 스레드나 핸들러를 조작하지 않고 백그라운드 작업을 하거나 UI 스레드에 결과물을 나타내게 해준다. 
AsyncTask 가 작동할 때는 다음 4단계를 따른다.
1. 작업이 시작하기 전에 UI 스레드에서 onPreExecute() 가 호출된다. 작업을 시작하기 위한 초기 세팅을 한다. ( UI에 진행 상황바를 보여주게 하는 등등의 작업 ) 
2. onPreExecute() 가 끝나자 마자 백그라운드 스레드에서 doInBackground(Params...) 가 호출된다. 이 단계에서 백그라운드 연산이 일어나고, 결과를 리턴하고, onPostExecute()로 결과가 전달된다. doInBackground() 메소드는 1개 이상의 작업을 보여주기 위해 publishProgress(Progress...) 를 호출할 수 있다.
3. onProgressUpdate(Progress...) 는 publishProgress(Progress...) 가 실행되고 나서 UI 스레드에서 실행된다. onProgressUpdate()는 UI 스레드로 어떤 형태의 진행상황을 보고 할 때 사용할 수 있다. (진행상황바를 나타내거나 텍스트필드에 로그를 보여주는 등)
4. onPostExecute(Result) 는 백그라운드 연산이 끝나고 나면 UI 스레드에서 실행된다.

AsyncTask 사용법

AsyncTask 클래스를 사용하려면, AsyncTask의 서브클래스를 정의하고 doInBackground(Params...) 메소드를 오버라이드 해야한다. (보통 onPostExecute(Result) 메소드도 오버라이드하게 된다.) 

AsyncTask 매개변수들

AsyncTask 클래스의 자식클래스를 선언할 때, 3개의 매개변수를 위한 데이터 타입을 지정해 주어야 한다.
  • "Params" 은 doInBackground() 메소드에 전달될 매개변수의 타입을 배열로 지정한다.
  • "Progress" 는 백그라운드 스레드에서 publishProgress() 에 전달될 매개변수의 타입을 지정한다. 이 매개변수들은 메인 스레드에 있는 onProgressUpdate()에도 전달되게 된다.
  • "Result" 는 doInBackground() 메소드가 리턴할 데이터의 타입을 지정해준다. 이 매개변수는 자동으로 메인 메소드에 있는 onPostExecute()에도 전달되게 된다. 
매개변수의 타입을 각각 따로 지정해주어야 하고, 사용하지 않는 매개변수인 경우에는 Void로 남겨두어야 한다. For example:
public class MyAsyncTask extends AsyncTask <String, Void, Bitmap>{}
In this class declaration:
  • "Params" 매개변수의 타입은 String 이다. MyAsyncTask  는 하나 이상의 문자열을 매개변수로 doInBackground()에 전달하게 된다. 예를 들어 쿼리를 하는데 이용할 수 있다.
  • "Progress" 매개변수는 Void로 지정되어 있다. 즉, the publishProgress() or onProgressUpdate() methods 에는 매개변수를 사용하지 않게 된다.
  • "Result" 매개변수의 타입은 Bitmap이다. MyAsyncTask 클래스는 doInbackground()  메소드에서 비트맵을 리턴하고, 이것을 onPostExecute()에 전달한다.

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");
     }
 }
  • doInBackground() 는 컨텐츠를 다운로드한다. (오래 걸리는 작업). 여기서는 for 루프에서 파일의 다운로드가 어느 정도 되었는지 퍼센티지로 계산하고, publishProgress()에 전달한다. for 루프에서 isCancelled()를 이용해서 작업이 취소되었는지를 체크한다. (무한루프 방지)
  • onProgressUpdate() 는 퍼센트 진행상황을 업데이트 해준다. publishProgress() 메소드는 doInBackground()안에서 계속 호출되고, 퍼센트로 진행상황을 업데이트해준다.  
  • doInBackground() 다운로드 받은 바이트의 전체 수를 계산해주고 리턴한다. onPostExecute() 는 리턴받은 변수를 onPostExecute() 로 전달한다 . onPostExecute()에서는 대화상자에 바이트 수를 나타낸다. 

AsyncTask 작동

AsyncTask의 서브클래스를 선언하고 나면, UI 스레드에서 인스턴스화 한다.
그런 다음. 인스턴스에서 execute() 를 호출하고 매개변수를 전달한다. 
(1.이때 매개변수의 개수는 상관이 없다. 2. "Params" 에서 선언된 매개변수의 타입으로 전달해야한다.)
위에서 선언한 예시에선 이렇게 쓸 수 있다.
new DownloadFilesTask().execute(url1, url2, url3);

AsyncTask 취소하기

cancel() 메소드를 이용하면 어느 스레드에서든, 언제든지 작업을 취소할 수 있다. 

  • 이미 취소된 경우에는 중복해서 취소할 수 없으므로 false를 리턴한다. 이외의 경우에는 true 리턴.
  • 작업이 취소됐는지 확인하기 위해서, doInBackground(Object[]) 에서isCancelled()의 리턴값을 주기적으로 확인해야한다. 
  • AsyncTask 작업이 취소되면, onPostExecute()는 호출되지 않는다. 대신, onCancelled(Object)가 호출된다. (디폴트로는 그저 무시하는 걸로 구현되어 있다.)
  • cancel() 이 진행중인 작업을 인터럽트하게 하려면 mayInterruptIfRunning 에 true를 전달해야한다. 

AsyncTask 클래스의 한계


몇몇 경우에 실용적이지 못하다. 

1. device 설정을 바꾸면 문제를 일으킨다.
  AsyncTask가 작동하는 도중에 디바이스 설정을 바꾸면(스크린회전 등), AsyncTask 가 만들어진 액티비티가 파괴되고 다시 만들어진다. AsyncTask는 새로 만들어진 액티비티에 접근할 수 없다.


2. 오래된 AsyncTask 객체가 계속 남아, 어플이 메모리부족이나 충돌을 일으킬 수 있다.
  AsyncTask를 만든 액티비티가 파괴될 때 AsyncTask가 같이 파괴되지 않는다.

AsyncTask는 제한적으로 사용해야한다.
  • 짧고 인터럽트할 수 있는 작업.
  • UI나 user에게 다시 무언가를 돌려줄 필요가 없는 작업
  • 완료되지 않은 채로 남아있어도 되는 중요도가 낮은 작업

다른 경우에는 Loader 프레임워크의 일부인 다음에 설명할 AsyncTaskLoader 클래스를 사용해야한다. 

.

piano (press key Q)

Categories

flutter ( 82 ) dart ( 34 ) android ( 32 ) kotlin ( 11 ) plugin ( 8 ) provider ( 8 ) vim ( 7 ) bloc ( 6 ) iOS ( 6 ) state management ( 6 ) 플러터 ( 6 ) PS ( 5 ) algorithm ( 5 ) architecture ( 5 ) async ( 5 ) getx ( 5 ) java ( 5 ) API ( 4 ) BOJ ( 4 ) class ( 4 ) daily ( 4 ) git ( 4 ) golang ( 4 ) memo ( 4 ) riverpod ( 4 ) state ( 4 ) stream ( 4 ) test ( 4 ) web ( 4 ) widget ( 4 ) windows ( 4 ) HTTP ( 3 ) androidX ( 3 ) app state ( 3 ) context ( 3 ) crash ( 3 ) db ( 3 ) editor ( 3 ) error ( 3 ) extension ( 3 ) github ( 3 ) hive ( 3 ) ide ( 3 ) package ( 3 ) pubspec ( 3 ) python ( 3 ) syntax ( 3 ) vscode ( 3 ) app icon ( 2 ) await ( 2 ) chocolatey ( 2 ) consumer ( 2 ) cp949 ( 2 ) deployment ( 2 ) dev ( 2 ) flavor ( 2 ) gesture ( 2 ) globalkey ( 2 ) go ( 2 ) google ( 2 ) hack ( 2 ) js ( 2 ) json ( 2 ) key ( 2 ) keystore ( 2 ) list ( 2 ) listview ( 2 ) lock ( 2 ) mac ( 2 ) map ( 2 ) navigation ( 2 ) nosql ( 2 ) project ( 2 ) pub ( 2 ) recyclerview ( 2 ) rxdart ( 2 ) sdk ( 2 ) selector ( 2 ) setting ( 2 ) size ( 2 ) soc ( 2 ) synchronized ( 2 ) tdd ( 2 ) tip ( 2 ) version ( 2 ) viewmodel ( 2 ) vundle ( 2 ) webview ( 2 ) xcode ( 2 ) yaml ( 2 ) ( 2 ) 플러터 단점 ( 2 ) 16.0 ( 1 ) 2.0 ( 1 ) 2023 ( 1 ) AATP2 ( 1 ) ChangeNotifierProvider ( 1 ) Example ( 1 ) Guava ( 1 ) ImageReader ( 1 ) Mo's algorithm ( 1 ) OAuth2 ( 1 ) OpenGL ( 1 ) Oreo ( 1 ) ProgressBar ( 1 ) REST API ( 1 ) Trie ( 1 ) activity ( 1 ) adaptive ( 1 ) android P ( 1 ) android context ( 1 ) android11 ( 1 ) apktool2 ( 1 ) app exit ( 1 ) append ( 1 ) appicon ( 1 ) arkit ( 1 ) array ( 1 ) asciidoc ( 1 ) async * ( 1 ) async* ( 1 ) audio ( 1 ) authorization ( 1 ) await for ( 1 ) behaviorsubject ( 1 ) beta ( 1 ) binary ( 1 ) binarysearch ( 1 ) blender ( 1 ) book ( 1 ) bottomsheet ( 1 ) break ( 1 ) broadcast ( 1 ) browser ( 1 ) bubbles ( 1 ) bug ( 1 ) build ( 1 ) buildcontext ( 1 ) buildnumber ( 1 ) bundle ( 1 ) button ( 1 ) bytecode ( 1 ) cache ( 1 ) camera2 ( 1 ) cameramanager ( 1 ) cd ( 1 ) chrome ( 1 ) ci ( 1 ) circle ( 1 ) clean ( 1 ) clean architecture ( 1 ) cli ( 1 ) clip ( 1 ) clipboard ( 1 ) cloud ide ( 1 ) cmdlet ( 1 ) code ( 1 ) coding test ( 1 ) command ( 1 ) comparator ( 1 ) complexity ( 1 ) concurrency ( 1 ) conditional ( 1 ) const ( 1 ) constraint ( 1 ) constraintlayout ( 1 ) controlc ( 1 ) controlv ( 1 ) converter ( 1 ) copy ( 1 ) copy project ( 1 ) coupling ( 1 ) coverage ( 1 ) cp ( 1 ) css ( 1 ) cupertino ( 1 ) cursor ( 1 ) cv ( 1 ) data class ( 1 ) data structure ( 1 ) dataBinding ( 1 ) database ( 1 ) debounce ( 1 ) decompile ( 1 ) delegate ( 1 ) deno ( 1 ) design pattern ( 1 ) development ( 1 ) device ( 1 ) di ( 1 ) dialog ( 1 ) dio ( 1 ) drawable ( 1 ) drug ( 1 ) emmet ( 1 ) encoding ( 1 ) english ( 1 ) entries ( 1 ) environment ( 1 ) equality ( 1 ) equatable ( 1 ) euc-kr ( 1 ) euckr ( 1 ) exit ( 1 ) expand ( 1 ) expanded ( 1 ) export ( 1 ) extension method ( 1 ) facade ( 1 ) fake ( 1 ) field ( 1 ) figma ( 1 ) final ( 1 ) fixed ( 1 ) flutter pub ( 1 ) flutter web ( 1 ) flutter_inappwebview ( 1 ) flutter_test ( 1 ) flutterflow ( 1 ) fold ( 1 ) fonts ( 1 ) form ( 1 ) frame ( 1 ) future ( 1 ) gestureDetector ( 1 ) gestureRecognizer ( 1 ) gesturearena ( 1 ) get-command ( 1 ) get_cli ( 1 ) getbuilder ( 1 ) getx단점 ( 1 ) gitignore ( 1 ) glut ( 1 ) google fonts ( 1 ) gopath ( 1 ) goto ( 1 ) gradient ( 1 ) graphics ( 1 ) gvim ( 1 ) hackaton ( 1 ) hash ( 1 ) hashmap ( 1 ) hot reload ( 1 ) how to ( 1 ) html ( 1 ) i18n ( 1 ) icon ( 1 ) id ( 1 ) impeller ( 1 ) implementation ( 1 ) import ( 1 ) indicator ( 1 ) inkwell ( 1 ) interrupt ( 1 ) intl ( 1 ) introduction ( 1 ) io ( 1 ) isar ( 1 ) iterable ( 1 ) iteration ( 1 ) javascript ( 1 ) julia ( 1 ) juno ( 1 ) jupyter ( 1 ) kakaomap ( 1 ) keytool ( 1 ) korean ( 1 ) kotlin syntax ( 1 ) l10n ( 1 ) lambda ( 1 ) language ( 1 ) layer ( 1 ) layout ( 1 ) lineageOS ( 1 ) localkey ( 1 ) localtoglobal ( 1 ) long list ( 1 ) ls ( 1 ) mac osx ( 1 ) markdown ( 1 ) markup ( 1 ) material ( 1 ) method ( 1 ) microtask ( 1 ) migrate ( 1 ) mintlify ( 1 ) mock ( 1 ) module ( 1 ) monitor ( 1 ) moor ( 1 ) mouse ( 1 ) mouseregion ( 1 ) multiplatform ( 1 ) multiset ( 1 ) multithread ( 1 ) mutable ( 1 ) mvvm ( 1 ) new ( 1 ) node ( 1 ) nodejs ( 1 ) nosuchmethod ( 1 ) null-safety ( 1 ) numberformat ( 1 ) nvim ( 1 ) object ( 1 ) objectbox ( 1 ) objectkey ( 1 ) obx ( 1 ) online ide ( 1 ) operator ( 1 ) orientation ( 1 ) parabeac ( 1 ) parse ( 1 ) paste ( 1 ) path ( 1 ) pattern ( 1 ) pitfall ( 1 ) play store ( 1 ) pod ( 1 ) podfile ( 1 ) pointer ( 1 ) pointers ( 1 ) powershell ( 1 ) private ( 1 ) programming ( 1 ) pull to refresh ( 1 ) puzzle ( 1 ) pycharm ( 1 ) realitykit ( 1 ) recursion ( 1 ) reduce ( 1 ) reference ( 1 ) regex ( 1 ) regular expression ( 1 ) release note ( 1 ) renderbox ( 1 ) renderobject ( 1 ) repl ( 1 ) repository ( 1 ) response ( 1 ) rm ( 1 ) rotue ( 1 ) round ( 1 ) run ( 1 ) scope ( 1 ) scroll ( 1 ) search ( 1 ) server ( 1 ) serverless ( 1 ) service ( 1 ) sharp ( 1 ) singlerepo ( 1 ) singleton ( 1 ) sketch ( 1 ) sliver ( 1 ) sliverlist ( 1 ) snippets ( 1 ) sogae ( 1 ) sorting ( 1 ) source ( 1 ) sparse ( 1 ) sparse array ( 1 ) spec ( 1 ) split ( 1 ) sqflite ( 1 ) sqlite ( 1 ) sqrt decomposition ( 1 ) stateful ( 1 ) statefulwidget ( 1 ) step ( 1 ) stepper ( 1 ) string ( 1 ) stringbuffer ( 1 ) stringbuilder ( 1 ) studio ( 1 ) study ( 1 ) sub-directory ( 1 ) svn ( 1 ) swiftui ( 1 ) swipe to refresh ( 1 ) system_alert_window ( 1 ) system_cache ( 1 ) systemnavigator ( 1 ) tail recursion ( 1 ) tailrec ( 1 ) tap test ( 1 ) text ( 1 ) texteditingcontroller ( 1 ) textfield ( 1 ) texttheme ( 1 ) themedata ( 1 ) then ( 1 ) thread ( 1 ) throttle ( 1 ) time ( 1 ) tool ( 1 ) tools ( 1 ) tooltip ( 1 ) ts ( 1 ) tutorial ( 1 ) typescript ( 1 ) ui ( 1 ) unittest ( 1 ) update ( 1 ) usb ( 1 ) utf8 ( 1 ) ux ( 1 ) valuekey ( 1 ) variable ( 1 ) vector ( 1 ) versioncode ( 1 ) very_good ( 1 ) view ( 1 ) vim plugin ( 1 ) vimrc ( 1 ) virtualenv ( 1 ) wasm ( 1 ) web app ( 1 ) webview_flutter ( 1 ) while ( 1 ) widget tree ( 1 ) window ( 1 ) wsl ( 1 ) yield ( 1 ) 강의 ( 1 ) 개발 ( 1 ) 개발 공부 ( 1 ) 공부법 ( 1 ) 그래픽스 ( 1 ) 꼬리재귀 ( 1 ) 꿀팁 ( 1 ) 데노 ( 1 ) 두줄 ( 1 ) 디노 ( 1 ) 번역 ( 1 ) 블록 ( 1 ) 상태관리 ( 1 ) 실험 ( 1 ) 안드로이드 ( 1 ) 안드로이드프로젝트 ( 1 ) 안드로이드프로젝트복사 ( 1 ) 어이없는 ( 1 ) 조건부 임포트 ( 1 ) 주절주절분노조절실패의식으흐름 ( 1 ) 패키지 ( 1 ) 프로젝트복사 ( 1 ) 플러그인 ( 1 )