AsyncTask異步任務(wù)的源碼詳細(xì)解析

1抱冷、AsyncTask基本使用:

AsyncTask asyncTask=new AsyncTask<Void,Void,Void>() {
            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
                //執(zhí)行完成返回的方法 UI 主線程
            }
            @Override
            protected Void doInBackground(Void... voids) {
                //執(zhí)行一些耗時(shí)操作 鏈接網(wǎng)絡(luò) 讀取大型的數(shù)據(jù)庫 運(yùn)行在Thread
                //在此方法中調(diào)用publishProgress();崔列,會將進(jìn)度值更新在onProgressUpdate(Void... values)方法中
                publishProgress();
                return null;
            }
            @Override
            protected void onPreExecute() {
                //一調(diào)用就會執(zhí)行的方法 更新UI 主線程
                super.onPreExecute();
            }
            @Override
            protected void onProgressUpdate(Void... values) {
                super.onProgressUpdate(values);
                //更新在doInBackground()方法中下載的進(jìn)度;
            }
        };
        asyncTask.execute("www.baidu.com");

2、AsyncTask源碼閱讀旺遮,點(diǎn)擊asyncTask.execute("www.baidu.com");中的execute("www.baidu.com")方法進(jìn)入AsyncTask的源碼...

@MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

調(diào)用AsyncTask內(nèi)部方法executeOnExecutor(sDefaultExecutor, params);點(diǎn)擊進(jìn)入該方法:

  @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {//初始狀態(tài)mStatus == Status.PENDING赵讯,所以第一次進(jìn)入該方法時(shí),不會進(jìn)入if()方法中耿眉。再次調(diào)用時(shí)边翼,根據(jù)狀態(tài)拋出異常。AsyncTask(同一對象)只能運(yùn)行一次
            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;//更新mStatus 的狀態(tài)為Running
        onPreExecute();//首先調(diào)用了這個(gè)方法
        mWorker.mParams = params;//將傳進(jìn)來的參數(shù)賦值給 mWorker.mParams鸣剪,在子線程中藥用到
        exec.execute(mFuture);//然后調(diào)用接口方法组底,應(yīng)為這是個(gè)接口,沒法往下看筐骇,所以在代碼中查找mFuture這個(gè)變量用到的地方
        return this;
    }
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);
                }
            }
        };

new FutureTask<Result>(mWorker) {}债鸡;得到mFuture對象,傳入一個(gè)mWorker對象:

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;
            }
        };

下面我們先來看看FutureTask是個(gè)什么東西:

public class FutureTask<V> implements RunnableFuture<V> {...}

首先它實(shí)現(xiàn)了RunnableFuture<V>接口,RunnableFuture<V>繼承Runnable接口铛纬,實(shí)現(xiàn)run()方法

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

所以在FutureTask<V>查找run()方法

public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

在run()方法中厌均,callable就是通過構(gòu)造方法傳進(jìn)來的mWorker這個(gè)參數(shù),result = c.call();

   public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

現(xiàn)在回到mWorker告唆,調(diào)用了call()方法:

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;
            }
        };

調(diào)用了result = doInBackground(mParams);方法棺弊,在finally{}中晶密,調(diào)用了postResult(result);將結(jié)果發(fā)送到主線程。
在AsyncTask中查找MESSAGE_POST_RESULT模她,發(fā)現(xiàn):調(diào)用了finish()方法

 private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
 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;
            }
        }
    }

那么finish()又是什么方法呢纱控?

    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

最后通過onPostExecute(result);將結(jié)果傳到主線程中去特姐,同時(shí)將mStatus = Status.FINISHED;變成Status.FINISHED雪猪。完成此AsyncTask對象的異步任務(wù)旋圆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市用狱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拼弃,老刑警劉巖夏伊,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吻氧,居然都是意外死亡溺忧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門盯孙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲁森,“玉大人,你說我怎么就攤上這事振惰「韪龋” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵骑晶,是天一觀的道長痛垛。 經(jīng)常有香客問我,道長桶蛔,這世上最難降的妖魔是什么匙头? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮仔雷,結(jié)果婚禮上蹂析,老公的妹妹穿的比我還像新娘。我一直安慰自己碟婆,他們只是感情好电抚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脑融,像睡著了一般喻频。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肘迎,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天甥温,我揣著相機(jī)與錄音锻煌,去河邊找鬼。 笑死姻蚓,一個(gè)胖子當(dāng)著我的面吹牛宋梧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狰挡,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捂龄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了加叁?” 一聲冷哼從身側(cè)響起倦沧,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎它匕,沒想到半個(gè)月后展融,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豫柬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年告希,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烧给。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡燕偶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出础嫡,到底是詐尸還是另有隱情指么,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布驰吓,位于F島的核電站涧尿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏檬贰。R本人自食惡果不足惜姑廉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翁涤。 院中可真熱鬧桥言,春花似錦、人聲如沸葵礼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸳粉。三九已至扔涧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枯夜。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工弯汰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人湖雹。 一個(gè)月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓咏闪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摔吏。 傳聞我的和親對象是個(gè)殘疾皇子鸽嫂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容