Android 에서 AsyncTask 의 작업 원 리 를 간단히 말 하 다

10673 단어 AndroidAsyncTask
개술
실제로 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 의 작업 원리 에 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기