[Android] AsyncTask 메커니즘
8723 단어 Android
AsyncTask 는 UI 스 레 드 를 쉽게 사용 할 수 있 습 니 다.백 스테이지 작업 을 허용 하고 결 과 를 UI 스 레 드 에 발표 합 니 다. 스 레 드 나 Handler 를 조작 하지 않 아 도 됩 니 다.AsyncTask 는 Thread, Handler 와 관련 된 도움말 클래스 로 설계 되 었 습 니 다.AsyncTask 는 짧 은 시간 (최대 몇 초) 의 작업 에 사 용 됩 니 다.
AsyncTask 사용 시 다음 과 같은 몇 가 지 를 주의해 야 합 니 다:
AsyncTask 가 처음 도 입 했 을 때 AsyncTask 의 임 무 는 직렬 이 었 습 니 다.Android 1.6 이후 AsyncTask 는 병행 으로 설계 되 었 다.Android 3.0 이후 AsyncTask 는 직렬 로 재 설계 되 었 다.3.0 이후 버 전에 서 병행 이 필요 하 다 면 AsyncTask 의 execute OnExecutor (java. util. concurrent. Executor, Object []) 방법 을 사용 하여 수 동 으로 Executor 에 전송 할 수 있 습 니 다.
AsyncTask 클래스 를 불 러 올 때 Thread PoolExecutor 를 초기 화 합 니 다.
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
그 중에서 핵심 스 레 드 수 는 최소 2 개, 최대 4 개 입 니 다.
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
최대 스 레 드 수 CPU 수량 * 2 + 1:
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
KeepAlive 시간 은 30s 입 니 다.
private static final int KEEP_ALIVE_SECONDS = 30;
퀘 스 트 대기 열 최대 128:
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
AsyncTask 의 기본 사용:
1. 하나의 종 류 를 정의 합 니 다. AsyncTask 에서 계승 하고 필요 에 따라 doInBackground (), onProgressUpdate (), onPostExecute () 방법 을 다시 작성 합 니 다. 보통 doInBackground (), onPostExecute () 방법 은 다시 써 야 합 니 다. 여기 서 자신의 업 무 를 실현 합 니 다.doInBackground () 방법 은 하위 스 레 드 에서 실 행 됩 니 다.onProgressUpdate () 와 onPostExecute () 는 UI 스 레 드 에서 실 행 됩 니 다.
private class DownloadFilesTask extends AsyncTask {
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");
}
}
2. DownloadFilesTask 의 인 스 턴 스 를 만 들 고 execute () 방법 을 실행 합 니 다.
new DownloadFilesTask().execute(url1, url2, url3);
다음은 소스 코드 측면 에서 AsyncTask 의 원 리 를 분석 해 보 자.
AsyncTask 의 실행 입 구 는 execute 방법 입 니 다.
@MainThread
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
execute () 방법 은 UI 스 레 드 에서 호출 되 어야 합 니 다.방법 내부 에서 execute OnExecutor () 방법 을 호출 하 였 습 니 다.
@MainThread
public final AsyncTask executeOnExecutor(Executor exec,
Params... params) {
// AsyncTask , ( ),
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
// RUNNING
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
execute OnExecutor () 방법 도 UI 스 레 드 에서 호출 해 야 합 니 다.방법 이 시 작 될 때 AsyncTask 상 태 를 검사 합 니 다. 실행 되 지 않 은 상태 (예 를 들 어 작업 이 실행 중이 거나 완료 되 었 을 때) 가 아 닌 이상 을 던 집 니 다.그 다음 에 작업 상 태 를 RUNNING 상태 로 설정 하고 onPreExecute () 방법 을 호출 합 니 다. 이 방법 은 스스로 재 작성 해 야 합 니 다. UI 알림 을 할 수 있 습 니 다.그리고 매개 변 수 를 mWorker 로 설정 하고 Executor 의 execute () 방법 을 호출 합 니 다.
기본 Executor 를 사용 하면 직렬 입 니 다.
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
다음은 sDefaultExecutor 의 정 의 를 살 펴 보 겠 습 니 다.
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
그리고 SERIALEXECUTOR 의 구체 적 인 실현 은 다음 과 같다.
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
mWorker 의 정의:
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
//
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
// doInBackground
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
//
postResult(result);
}
return result;
}
};
execute () 방법 을 실행 하면 mWorker 의 call () 방법 을 호출 합 니 다. 이 방법 에서 스 레 드 를 배경 스 레 드 로 설정 한 다음 doInBackground () 방법 을 호출 하고 실행 이 끝 난 후에 post Result () 방법 을 호출 합 니 다.doInBackground () 방법 에 서 는 PublishProgress () 방법 을 사용 하여 진행 정 보 를 UI 스 레 드 에 보 낼 수 있 습 니 다.
postResult () 방법:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
Handler 에 메시지 보 내기.
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult> result = (AsyncTaskResult>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
Handler 의 handle Message () 방법 에서 메 시 지 를 처리 합 니 다.실행 이 완료 되면 AsyncTask 의 finish () 방법 을 사용 합 니 다. 업데이트 진도 라면 AsyncTask 의 onProgressUpdate () 방법 을 사용 합 니 다.
private void finish(Result result) {
if (isCancelled()) {
// , onCancelled() 。
onCancelled(result);
} else {
// onPostExecute()
onPostExecute(result);
}
// FINISHED
mStatus = Status.FINISHED;
}
@MainThread
protected void onProgressUpdate(Progress... values) {
}
publishProgress () 방법:
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.