Android 에서 AsyncTask 의 작업 원 리 를 간단히 말 하 다
실제로 AsyncTask 내 부 는 Thread 와 Handler 가 봉 인 돼 있다.AsyncTask 는 백 스테이지 작업 을 편리 하 게 수행 하고 메 인 스 레 드 에서 UI 를 업데이트 하지만 AsyncTask 는 특별히 시간 이 걸 리 는 백 스테이지 작업 에 적합 하지 않 습 니 다.특히 시간 이 걸 리 는 작업 에 대해 서 는 개인 적 으로 스 레 드 풀 을 사용 하 는 것 을 권장 합 니 다.자,긴 말 하지 않 겠 습 니 다.우선 AsyncTask 의 간단 한 용법 을 살 펴 보 겠 습 니 다.
AsyncTask 사용 방법
AsyncTask 는 추상 적 인 범 형 류 이다.간단하게 사용 방식 코드 를 소개 하 겠 습 니 다.다음 과 같 습 니 다.
package com.example.huangjialin.myapplication;
import android.os.AsyncTask;
import android.util.Log;
public class AsyncTaskTest extends AsyncTask<String, Object, Long>{
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("AsyncTaskTest","--- ---");
}
@Override
protected Long doInBackground(String... params) {
Log.i("AsyncTaskTest","--- ---");
return null;
}
@Override
protected void onProgressUpdate(Object... values) {
super.onProgressUpdate(values);
Log.i("AsyncTaskTest","--- ---");
}
@Override
protected void onPostExecute(Long aLong) {
super.onPostExecute(aLong);
Log.i("AsyncTaskTest","--- , --");
}
}
그리고 activity 에서 new AsyncTaskTest().execute()를 호출 합 니 다.됐 습 니 다..사용 하기 가 쉬 워 요.어떻게 사용 하 는 지 는 설명 하지 않 겠 습 니 다.AsyncTask 의 4 가지 핵심 방법
1.onPreExecute():이 방법 은 메 인 스 레 드 에서 실 행 됩 니 다.비동기 작업 을 수행 하기 전에 호출 됩 니 다.보통 준비 작업 에 사 용 됩 니 다.
2.doInBackground(String...params):이 방법 은 온라인 풀 에서 실 행 됩 니 다.이 방법 은 비동기 작업 을 수행 하 는 데 사 용 됩 니 다.이 방법 에서 publishProgress 방법 을 통 해 작업 의 진 도 를 업데이트 할 수 있 습 니 다.publishProgress 방법 은 onProgressUpdate 방법 을 호출 합 니 다.또한 작업 의 결 과 는 onPostExecute 방법 으로 되 돌아 갑 니 다.
3.onProgressUpdate(Object...values):이 방법 은 주 스 레 드 에서 실 행 됩 니 다.주로 작업 진도 업데이트 에 사 용 될 때 이 방법 이 호출 됩 니 다.
4.onPost Execute(Long aLong):메 인 스 레 드 에서 실 행 됩 니 다.비동기 작업 이 실 행 된 후에 이 방법 은 호출 됩 니 다.이 방법의 매개 변수 와 배경 으로 되 돌아 오 는 결과 입 니 다.
이 몇 가지 방법 외 에 도 onCanceled()와 같은 자주 사용 되 지 않 는 방법 도 있 습 니 다.비동기 작업 이 취 소 된 경우 이 방법 은 호출 됩 니 다.
자,AsyncTask 의 기본 적 인 사용 은 여기까지 입 니 다.다음은 주제 에 들 어가 서 AsyncTask 의 작업 원 리 를 살 펴 보 겠 습 니 다.
AsyncTask 의 작업 원리
먼저 execute 부터 시작 해서 소스 코드 가 왔 습 니 다.
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
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)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
방면 분석 을 위해 서 나 는 영어 주석 을 해 치 웠 다.원본 코드 는 위의 execute 방법 내부 에서 execute OnExecutor()방법 을 호출 한 것 을 알 수 있다.sDefaultExecutor 는 사실상 직렬 스 레 드 탱크 입 니 다.onPreExecute()방법 은 여기 서 호출 됩 니 다.이어서 이 스 레 드 탱크 를 보 세 요.
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
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);
}
}
}
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
위의 코드 를 통 해 알 수 있 듯 이 AsyncTask 의 실행 은 줄 을 서서 실 행 됩 니 다.키워드 synchronized 가 있 기 때문에 AsyncTask 의 Params 인 자 는 Future Task 류 로 봉 인 됩 니 다.Future Task 라 는 종 류 는 병발 류 로 여기 서 Runnable 의 역할 을 합 니 다.이 어 FutureTask 는 SerialExecutor 의 execute 방법 에 맡 기 고 SerialExecutor 의 executor 방법 은 먼저 FutureTask 를 mTasks 대기 열 에 추가 합 니 다.이때 작업 이 없 으 면 scheduleNext()방법 으로 다음 작업 을 수행 합 니 다.작업 이 있 으 면 실행 이 끝 난 후 마지막 으로 scheduleNext()를 호출 합 니 다.다음 임 무 를 수행 하 다.모든 임무 가 실 행 될 때 까지한편,AsyncTask 의 구조 방법 에는 call()방법 이 있 는데 이 방법 은 Future Task 의 run 방법 에 의 해 실 행 됩 니 다.그래서 결국 이 콜 방법 은 온라인 풀 에서 실 행 될 것 이다.doIn Background 라 는 방법 은 여기 서 호출 된 것 입 니 다.우 리 는 이 콜()방법 을 잘 연구 해 보 자.
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
mTaskInvoked.set(true);현재 임무 가 이미 집행 되 었 음 을 나타 낸다.이 어 doInBackground 방법 을 실행 하고 결 과 를 post Result(result)로 통과 합 니 다.방법 을 전달 하 다.postResult()방법 에 서 는 sHandler 를 통 해 메 시 지 를 보 냅 니 다.sHandler 의 코드 는 다음 과 같 습 니 다.
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@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;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
메모:AsyncTask 에는 두 개의 스 레 드 탱크 가 있 습 니 다.하 나 는 SerialExecutor 이 고 다른 하 나 는 THREAD 입 니 다.POOL_EXECUTOR,그 중에서 전 자 는 주로 임무 가 줄 을 서 는 것 이 고 후 자 는 진정한 임 무 를 수행 하 는 것 이다.한편,AsyncTask 에는 Internal Handler 방법 도 있 는데 이 방법의 주요 역할 은 실행 환경 을 스 레 드 탱크 에서 메 인 스 레 드 로 전환 하 는 것 이다.
이상 은 안 드 로 이 드 에서 AsyncTask 의 작업 원리 에 대한 상세 한 내용 입 니 다.안 드 로 이 드 에서 AsyncTask 의 작업 원리 에 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.