티스토리 뷰
onPreExecute()
onProgressUpdate()
onPostExecute()
onCancelled()
위에 나온 4개의 AsyncTask 콜백함수들은 메인쓰레드에서 실행된다.
doInBackground()
작업쓰레드가 실행되면 수행되는 이 핵심 콜백 함수는 작업 쓰레드에서 별도로 실행 되며, 중간중간 메인쓰레드에 업데이트된 내용을 화면에 출력하게끔 publishProgress()메소드를 호출한다.
그럼 메인쓰레드에서 onProgressUpdate()콜백함수가 호출되어 화면에 현재 몇퍼센트 진행 되었다고 표시를 할 수 있게 된다.
메인쓰레드에서는 사용자 반응성이 중요하기 때문에 오래걸리는 작업을 처리하면 안된다. 오래걸리는 작업은 작업 쓰레드로 따로 분리하여 처리해야 한다.
원래 위의 AsyncTask가 없었다면 작업쓰레드 클래스를 따로 만들고 그 쓰레드에 핸들러와 루퍼를 따로 구현 한 다음에 메인쓰레드에서 작업쓰레드로 작업쓰레드에서 메인쓰레드로 쓰레드간 메세지를 전달함으로써 어떤 오래걸리는 작업을 처리해야
한다.
하지만 이 작업이 매우 번거로우므로 AsyncTask라는 제네릭 클래스가 등장하게 되었고 이것을 상속받아 오버라이딩 콜백 메소드들을 구현하게 되면 위의 과정을 쉽게 처리할수 있게 된다.
다만, 어떤 콜백함수가 메인쓰레드, 작업쓰레드에서 실행되는지는 구분하여 알아둘 필요가 있는것이다.
또한 AsyncTask에는 3가지 상태가 존재한다.
상태 |
설명 |
Status.PENDING |
AsyncTask객체 생성만하고 execute로 실행하지 않은 경우 |
Status.RUNNING |
execute()로 AsyncTask를 실행한 상태 |
Status.FINISHED |
종료 |
AsyncTask를 상속받는 at라는 객체가 있다고 해보자.
if(at.getStatus() == Status.FINISHED)
이런식으로 조건문을 걸게 되면 현재 AsyncTask가 끝났는지 아닌지 확인을 할 수 있다.
API 11 허니콤 이후부터는 둘이상의 AsyncTask를 동시에 실행 시킬때 두개의 쓰레드가 동시에 실행되는것이 아니고, 순서대로 실행되게끔 수정되었다. 그전에는 무조건 동시에 실행 되었다. 이렇게 하는것이 안정성이 높기 때문이다.
즉 at.execute()를 실행하게 되면 무조건 쓰레드가 실행된 순서대로 먼저 돌아가고 at.executeOnExecuter()를 실행하면 동시실행인지, 순서 실행인지 매개변수에 따라 결정할 수 있다.
at.cancel(true);를 통해서 AsyncTask를 종료시키면 무슨일이 일어날까?
예상 대로 그냥 작업쓰레드가 바로 종료 될까? 아니다.
cancel이 호출된 시점부터는 doInBackground()내에서 publishProgress()를 아무리 호출한다고 하더라도 메인쓰레드에서 OnProgressUpdate() 콜백 함수가 호출 되지 않는다. 즉 작업쓰레드가 바로 종료되지 않고 계속 실행되는데, 메인쓰레드로 메세지를 보낼수는 없는 상태가 되는것이다.
cancel을 호출했을때 작업쓰레드를 바로 종료시킬 수 있는 간단한 방법으로는 doInBackground()내에서 Thread.sleep(1000);과 같은 slow system call을 호출하면 된다.
그렇게 되면 쓰레드가 슬립되었을때 cancel이 실행되면 인터럽트 예외가 발생되어서 작업쓰레드가 종료된다.
마치, 유닉스에서 슬로우 시스템콜에서 블락되어 있을때 시그널을 받아서 시그널 핸들러가 호출되고 그때 슬로우 시스템콜은 인터럽트 되어 에러 리턴되는것과 비슷한것이다.
하지만 이런방식으로 작업쓰레드를 종료 시키는것은 별로 좋아보이지 않는다.
AsyncTask클래스에는 현재 작업이 cancel()함수 호출에 의해 종료를 요청 받았는지 확인하는 함수가 있다.
바로 isCancelled()함수이다. 이 함수를 사용하면 사용자가 이 AsyncTask를 종료시키기 위해서 cancel()함수를 호출했는지 여부를 확인 할 수 있다. 이 함수는 확인을 원하는 위치 어느곳에나 삽입할수 있으므로 AsyncTask를 종료시킬때 좀 더 좋은 방법이라고 할 수 있다.
cancel(true)와 cancel(false)에서 매개변수로 전달하는 true,false의 의미
doInBackground()함수 내에서 어떤 쓰레드 관련 함수를 실행시키는 상태였을때 InterruptedException을 발생 시키고 싶으면 true를 매개변수로 전달하고 발생시키고 싶지 않으면 false를 전달하면 된다.
다시말해서, cancel을 호출하자마자 쓰레드내부에서 뭐가 실행되고 있건간에 바로 종료시키고 싶으면 true를 매개변수로 전달하면 되고, 현재 실행되고 있는것은 마무리 된 다음에 종료 시키고 싶으면 false를 전달하면 된다.
(작업쓰레드)doInBackground() 내부에서 sleep()이 호출된 상태에서 메인쓰레드에서 at.cancel(true)을 실행하면 작업쓰레드에서 인터럽트예외가 발생되고 try catch문에 의해서 작업 쓰레드를 종료 시킬 수 있다.
-> 첫번째 나온 방법
메인쓰레드에서 at.cancel(false);를 실행시키고 (작업쓰레드)doInBackground()내부에서
if(isCancelled() == true)이런식으로 확인하여 doInBackground를 바로 리턴시킴으로써 작업쓰레드를 종료시키는 방법도 있다.
-> 두번째 방법
'컴퓨터 공학과 졸업 > 안드 개발 기록' 카테고리의 다른 글
하단바 만들기 (0) | 2018.07.12 |
---|---|
프래그먼트 (0) | 2018.07.12 |
네비게이션 드로어 (0) | 2018.07.04 |
[퍼옴] RecyclerView (0) | 2018.07.03 |
DP단위 (0) | 2018.06.29 |
- Total
- Today
- Yesterday
- return type
- hydrate
- reflow
- await
- webpack
- Next.js
- Polyfill
- useEffect
- Babel
- javascript
- atomic design
- promise
- react hooks
- rendering scope
- props
- type alias
- Action
- server side rendering
- es6
- react
- state
- async
- reactdom
- mobx
- storybook
- typescript
- design system
- reducer
- computed
- useRef
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |