動(dòng)手實(shí)現(xiàn)AsyncTask v1.1

AsyncTask.java
AsycnTask-Api
AsyncTask是后臺(tái)執(zhí)行操作在UI線程發(fā)布結(jié)果的對(duì)象,很輕松的使用UI線程,用于耗時(shí)較短的后臺(tái)操作癞志。

AsyncTask原理

  • AsyncTas類初始化sDefaultExecutor和sHandler變量,用于執(zhí)行后臺(tái)執(zhí)行任務(wù)和分發(fā)消息給主線程

  • AsyncTask對(duì)象創(chuàng)建時(shí)實(shí)現(xiàn)后臺(tái)執(zhí)行函數(shù)doInBackground()和發(fā)布UI結(jié)果的回調(diào)函數(shù)onPostExecute()

  • 構(gòu)造AsyncTask時(shí)

  • 構(gòu)建類型為WorkerRunnable的mWork對(duì)象,執(zhí)行doInBackground()糠赦,然后發(fā)送結(jié)束消息給sHandler

  • 構(gòu)建類型FutureTask的mFuture對(duì)象,以mWork為回調(diào)參數(shù)锅棕,并重寫任務(wù)結(jié)束回調(diào)方法done()拙泽,如果上面沒(méi)有發(fā)送消息沒(méi)有成功會(huì)再次發(fā)給sHandler

  • mWork和mFuture中發(fā)送消息都調(diào)用postResult(),message的obj指向的是AsyncTaskResult對(duì)象裸燎,其包含AsyncTask對(duì)象和消息類型標(biāo)記

  • execute()啟動(dòng)時(shí)在執(zhí)行線程池處理任務(wù)之前先調(diào)用onPreExecute()

  • mFuture進(jìn)入sDefaultExecutor線程池任務(wù)隊(duì)列消費(fèi)

  • 任務(wù)執(zhí)行結(jié)束調(diào)用FutureTask的done()方法顾瞻,將執(zhí)行完畢消息通過(guò)postResult()發(fā)送給sHandler

  • sHandler收到消息根據(jù)what標(biāo)記分別調(diào)用asyncTask對(duì)象的發(fā)布結(jié)果回調(diào)方法和更新UI進(jìn)度方法

注明:
AsyncTask必須在主線程中創(chuàng)建
后臺(tái)執(zhí)行回調(diào)調(diào)用publishProgress()就是發(fā)送更新進(jìn)度消息給sHandler

動(dòng)手實(shí)現(xiàn)

public abstract class AsyncTask<Params, Progress, Result> {
    private static final int MESSAGE_POST_RESULT = 1;//結(jié)束標(biāo)記
    private static final int MESSAGE_POST_PROGRESS = 2;//更新進(jìn)度標(biāo)記

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//cpu核心數(shù)

    //最少2個(gè)或者4個(gè)核心線程
    //cpu核心數(shù)少一個(gè)線程,以免飽和
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    //線程創(chuàng)建工廠
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            ////參數(shù)2為線程名字
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };
    //最多容納128個(gè)任務(wù)德绿,再多任務(wù)就會(huì)被阻塞
    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    static {
        //初始化線程執(zhí)行器配置
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        sDefaultExecutor = threadPoolExecutor;//暫不使用哪個(gè)串行執(zhí)行的執(zhí)行器
    }

    private static volatile Executor sDefaultExecutor;
    private static InternalHandler sHnadler;

    //不適用懶加載直接使用
    static {
        sHnadler = new InternalHandler();
    }

    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;

    public AsyncTask() {
        //mWorker的參數(shù)在execute的時(shí)候補(bǔ)上
        mWorker = new WorkerRunnable<Params, Result>() {
            @Override
            public Result call() throws Exception {
                Result result = doInBackground(mParams);//調(diào)用后臺(tái)執(zhí)行操作
                postResult(result);//通知handler調(diào)用發(fā)布結(jié)果回調(diào)
                return result;
            }
        };
        mFuture = new FutureTask<Result>(mWorker);//暫不包裝二次檢查發(fā)送
    }

    //發(fā)送結(jié)束消息給handler
    private void postResult(Result result) {
        Message message = Message.obtain();
        message.what = MESSAGE_POST_RESULT;
        message.obj = new AsyncTaskResult(this, result);

    }

    //發(fā)送更新消息給handler
    protected void publishProgress(Progress... values) {
        Message message = Message.obtain();
        message.what = MESSAGE_POST_PROGRESS;
        message.obj = new AsyncTaskResult(this, values);
    }

    //執(zhí)行任務(wù)
    public void execute(Params... values) {
        onPreExecute();
        mWorker.mParams = values;
        sDefaultExecutor.execute(mFuture);
    }

    protected void onPreExecute() {
    }

    //后臺(tái)操作回調(diào)
    protected abstract Result doInBackground(Params... var1);

    //發(fā)布結(jié)果回調(diào)
    protected void onPostExecute(Result result) {
    }

   //進(jìn)度回調(diào)
    protected void onProgressUpdate(Progress... values) {
    }

    //主線程處理消息調(diào)用asyncTask的回調(diào)
    private static class InternalHandler extends Handler {

        public InternalHandler() {
            super(Looper.getMainLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    result.mTask.onPostExecute(result.mData[0]);//發(fā)布結(jié)果回調(diào)
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);//更新進(jìn)度回調(diào)
                    break;
            }
        }
    }

    //通過(guò)線程傳遞給doInBackground用戶定義好的參數(shù)
    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

    //消息攜帶類
    private static class AsyncTaskResult<Result> {
        AsyncTask mTask;//消息發(fā)送所屬AsyncTask
        Result[] mData;//結(jié)果參數(shù)

        public AsyncTaskResult(AsyncTask mTask, Result... mData) {
            this.mTask = mTask;
            this.mData = mData;
        }
    }
}

使用

asyncTask.execute("http://www.baidu.com");
...
    AsyncTask<String, Long, String> asyncTask = new AsyncTask<String, Long, String>() {
        @Override
        protected String doInBackground(String... strings) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }

        @Override
        protected void onPostExecute(String value) {
            super.onPostExecute(value);
            Toast.makeText(MainActivity.this, value + " over", Toast.LENGTH_SHORT).show();
        }
    };
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末荷荤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子移稳,更是在濱河造成了極大的恐慌蕴纳,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件个粱,死亡現(xiàn)場(chǎng)離奇詭異古毛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)都许,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門稻薇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人梭稚,你說(shuō)我怎么就攤上這事颖低。” “怎么了弧烤?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵忱屑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我暇昂,道長(zhǎng)莺戒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任急波,我火速辦了婚禮从铲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘澄暮。我一直安慰自己名段,他們只是感情好阱扬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伸辟,像睡著了一般麻惶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上信夫,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天窃蹋,我揣著相機(jī)與錄音,去河邊找鬼静稻。 笑死警没,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的振湾。 我是一名探鬼主播杀迹,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼恰梢!你這毒婦竟也來(lái)了佛南?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嵌言,失蹤者是張志新(化名)和其女友劉穎嗅回,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摧茴,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绵载,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苛白。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娃豹。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖购裙,靈堂內(nèi)的尸體忽然破棺而出懂版,到底是詐尸還是另有隱情,我是刑警寧澤躏率,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布躯畴,位于F島的核電站,受9級(jí)特大地震影響薇芝,放射性物質(zhì)發(fā)生泄漏蓬抄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一夯到、第九天 我趴在偏房一處隱蔽的房頂上張望嚷缭。 院中可真熱鬧,春花似錦、人聲如沸阅爽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)优床。三九已至劝赔,卻和暖如春誓焦,著一層夾襖步出監(jiān)牢的瞬間胆敞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工杂伟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留移层,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓赫粥,卻偏偏與公主長(zhǎng)得像观话,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子越平,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • Android開發(fā)者:你真的會(huì)用AsyncTask嗎频蛔? 導(dǎo)讀.1 在Android應(yīng)用開發(fā)中,我們需要時(shí)刻注意保證...
    cxm11閱讀 2,709評(píng)論 0 29
  • Android Handler機(jī)制系列文章整體內(nèi)容如下: Android Handler機(jī)制1之ThreadAnd...
    隔壁老李頭閱讀 3,210評(píng)論 1 15
  • AsyncTask異步任務(wù)秦叛,用于執(zhí)行耗時(shí)任務(wù)并在UI線程中更新結(jié)果晦溪。 我們都知道,Android UI線程中不能執(zhí)...
    iyifei閱讀 3,470評(píng)論 2 9
  • 環(huán)境依賴 GrayLog 服務(wù)端需要一些環(huán)境依賴 Linux 發(fā)行版(如Debian挣跋、Ubuntu三圆、或推薦使用的C...
    水車閱讀 602評(píng)論 0 1
  • 紀(jì)念永遠(yuǎn)的林肯公園 北京時(shí)間2017年7月21號(hào),總感覺(jué)今天會(huì)有大事發(fā)生避咆,接到停電消息舟肉,以為今天就是沒(méi)電。因?yàn)闆](méi)電...
    舟?閱讀 283評(píng)論 6 0