Android異步處理的幾種方式(附demo)

在Android的程序開發(fā)中碧磅,許多耗時(shí)操作都要放到子線程中例获,避免阻塞主線程杈抢,導(dǎo)致ANR神汹。但是在使用異步線程的過程中都會(huì)遇到與主線程通信的問題庆捺。
在這里先總體介紹幾種常見異步處理的技術(shù),以及他們的對(duì)應(yīng)關(guān)系:

Paste_Image.png

Thread

使用Thread有兩種方式屁魏,一直是使用Thread滔以,一種是使用Runnable。

Thread方式:

 public class MyThread extends Thread{
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mHandler.sendEmptyMessage(0);
        }
    }

然后在使用的時(shí)候調(diào)用

  new MyThread().start();

Runnable

 public class MyRunnable implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mHandler.sendEmptyMessage(0);
        }
    }

使用的時(shí)候調(diào)用:

 new Thread(new MyRunnable()).start();

總結(jié)

線程是執(zhí)行任務(wù)的最基本的單元氓拼,在Android開發(fā)中你画,線程又分為主線程和子線程,主線程中不能進(jìn)行耗時(shí)的操作桃漾,比如網(wǎng)絡(luò)請(qǐng)求坏匪,子線程中不能執(zhí)行更新UI的相關(guān)操作,否則都會(huì)拋出異常呈队。
根據(jù)上述例子可以看出剥槐,使用Thread執(zhí)行任務(wù),在結(jié)束后宪摧,需要通過Handler來發(fā)送消息粒竖,通知UI主線程,進(jìn)行對(duì)應(yīng)的界面更新几于。

HandlerThread

上面提到過Thread執(zhí)行完任務(wù)需要Handler來通知主線程蕊苗,HandlerThread集合了Thread和Handler,集成了Looper和MessageQueue沿彭。當(dāng)啟動(dòng)HandlerThread時(shí)朽砰,會(huì)同時(shí)生成Looper和MessageQueue,然后等待消息處理喉刘。
這里簡單寫一下:

 private class myBackRunnable implements Runnable{

        @Override
        public void run() {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mainHandler.post(new myUIRunnable());
        }
    }
    private class myUIRunnable implements Runnable{

        @Override
        public void run() {
            btnStart.setText("線程結(jié)束");
        }
    }

啟動(dòng)子線程:

 backHandler = new Handler(handlerThread.getLooper());
  mainHandler = new Handler(getMainLooper());
  backHandler.post(new myBackRunnable());

AsyncTask

AsyncTask提供了方便的接口實(shí)現(xiàn)工作線程和主線程的通信瞧柔,我這里先貼一下代碼,后面再根據(jù)代碼進(jìn)行解釋:

public class MyAsyncTask extends AsyncTask<Integer, String, String> {
        private Button btn;
        public MyAsyncTask(Button btn) {
            super();
            this.btn = btn;
        }
  
        @Override
        protected String doInBackground(Integer... integers) {
            Log.e("xxxxxx","xxxxxxexecute傳入?yún)?shù)="+integers[0]);
            try {
                Thread.sleep(1000);
                publishProgress("過了一秒");
                Thread.sleep(1000);
                publishProgress("過了兩秒");
                Thread.sleep(1000);
                publishProgress("過了三秒");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "doInBackground的返回";
        }
        /**
         * 這里的String參數(shù)對(duì)應(yīng)AsyncTask中的第三個(gè)參數(shù)(也就是接收doInBackground的返回值)
         * 在doInBackground方法執(zhí)行結(jié)束之后在運(yùn)行睦裳,并且運(yùn)行在UI線程當(dāng)中 可以對(duì)UI空間進(jìn)行設(shè)置
         */
        @Override
        protected void onPostExecute(String result) {
            btn.setText("線程結(jié)束" + result);
        }
        //該方法運(yùn)行在UI線程當(dāng)中,并且運(yùn)行在UI線程當(dāng)中 可以對(duì)UI空間進(jìn)行設(shè)置
        @Override
        protected void onPreExecute() {
            btn.setText("開始執(zhí)行異步線程");
        }
        /**
         * 這里的Intege參數(shù)對(duì)應(yīng)AsyncTask中的第二個(gè)參數(shù)
         * 在doInBackground方法當(dāng)中造锅,,每次調(diào)用publishProgress方法都會(huì)觸發(fā)onProgressUpdate執(zhí)行
         * onProgressUpdate是在UI線程中執(zhí)行廉邑,所有可以對(duì)UI空間進(jìn)行操作
         */
        @Override
        protected void onProgressUpdate(String... values) {

            String vlaue = values[0]+"";
            Log.e("xxxxxx","xxxxxx vlaue="+vlaue);
            btn.setText(vlaue+"");


        }
    }

AsyncTask就是一個(gè)封裝過的后臺(tái)任務(wù)類哥蔚,顧名思義就是異步任務(wù)倒谷。
AsyncTask定義了三種泛型類型 Params,Progress和Result糙箍。

Params 啟動(dòng)任務(wù)執(zhí)行的輸入?yún)?shù)渤愁,比如HTTP請(qǐng)求的URL。
Progress 后臺(tái)任務(wù)執(zhí)行的百分比深夯。
Result 后臺(tái)執(zhí)行任務(wù)最終返回的結(jié)果抖格,比如String。
對(duì)應(yīng)到上面的demo就是Integer, String, String塌西。
doInBackground(Params…) 后臺(tái)執(zhí)行他挎,比較耗時(shí)的操作都可以放在這里。注意這里不能直接操作UI捡需。此方法在后臺(tái)線程執(zhí)行办桨,完成任務(wù)的主要工作,通常需要較長的時(shí)間站辉。在執(zhí)行過程中可以調(diào)用publicProgress(Progress…)來更新任務(wù)的進(jìn)度呢撞。
onProgressUpdate(String... Progress)這里對(duì)應(yīng)的是doInBackground中調(diào)用的publicProgress,在這里進(jìn)行處理饰剥,這里是UI主線程可以進(jìn)行界面的更新
onPreExecute()這里相當(dāng)于線程的開始殊霞,可以進(jìn)行UI的處理
onPostExecute(Result) 相當(dāng)于Handler 處理UI的方式,在這里面可以使用在doInBackground 得到的結(jié)果處理操作UI汰蓉。 此方法在主線程執(zhí)行绷蹲,任務(wù)執(zhí)行的結(jié)果作為此方法的參數(shù)返回。
我們?cè)賮砜匆幌氯绾伍_啟

  myAsyncTask.execute(1000);

execute的參數(shù)對(duì)應(yīng)的就是上面提到過的Params顾孽。

IntentService

IntentService具有Service一樣的生命周期祝钢,也提供了后臺(tái)線程中的異步處理機(jī)制。還是先看一下代碼吧若厚。

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        try {
            Thread.sleep(3*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Intent intentresult = new Intent(IntentServiceActivity.RESULT);

        sendBroadcast(intentresult);
    }
    public void onDestroy()
    {
        super.onDestroy();
    }
}

這里我們是通過廣播拦英,將結(jié)果返回到源Activity進(jìn)行界面更新的,這樣的處理方式感覺很重测秸,如非設(shè)計(jì)流程需要使用疤估,不建議經(jīng)常使用。
再看一下如何啟動(dòng):
Intent intent=new Intent(IntentServiceActivity.this,MyIntentService.class);
startService(intent);

其他

AsyncQueryHandler是用于在ContentProvider上面執(zhí)行異步操作的工具類霎冯,筆者自己也不常用铃拇,這里不再贅述。
Exector框架的基礎(chǔ)是一個(gè)名為Exector的接口定義沈撞,Exector的主要任務(wù)是分離任務(wù)的創(chuàng)建和他的執(zhí)行锚贱。這個(gè)我將在下一篇文章線程池相關(guān)的介紹中詳細(xì)描述。
上面介紹過的所有異步機(jī)制关串,我已經(jīng)整理出一個(gè)demo工程拧廊,方便開發(fā)者測試:
https://github.com/mymdeep/TestAsynchronous

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晋修,隨后出現(xiàn)的幾起案子吧碾,更是在濱河造成了極大的恐慌,老刑警劉巖墓卦,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倦春,死亡現(xiàn)場離奇詭異,居然都是意外死亡落剪,警方通過查閱死者的電腦和手機(jī)睁本,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忠怖,“玉大人呢堰,你說我怎么就攤上這事》财” “怎么了枉疼?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鞋拟。 經(jīng)常有香客問我骂维,道長,這世上最難降的妖魔是什么贺纲? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任航闺,我火速辦了婚禮,結(jié)果婚禮上猴誊,老公的妹妹穿的比我還像新娘潦刃。我一直安慰自己,他們只是感情好稠肘,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布福铅。 她就那樣靜靜地躺著,像睡著了一般项阴。 火紅的嫁衣襯著肌膚如雪滑黔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天环揽,我揣著相機(jī)與錄音略荡,去河邊找鬼。 笑死歉胶,一個(gè)胖子當(dāng)著我的面吹牛汛兜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播通今,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼粥谬,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼肛根!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起漏策,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤派哲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后掺喻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芭届,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年感耙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了褂乍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡即硼,死狀恐怖逃片,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谦絮,我是刑警寧澤题诵,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站层皱,受9級(jí)特大地震影響性锭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叫胖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一草冈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓮增,春花似錦怎棱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至砸捏,卻和暖如春谬运,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垦藏。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工梆暖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掂骏。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓轰驳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子级解,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評(píng)論 25 707
  • Android開發(fā)者:你真的會(huì)用AsyncTask嗎冒黑? 導(dǎo)讀.1 在Android應(yīng)用開發(fā)中,我們需要時(shí)刻注意保證...
    cxm11閱讀 2,701評(píng)論 0 29
  • 在程序開發(fā)的實(shí)踐當(dāng)中蠕趁,為了讓程序表現(xiàn)得更加流暢薛闪,我們肯定會(huì)需要使用到多線程來提升程序的并發(fā)執(zhí)行性能。但是編寫多線程...
    MaxHere閱讀 3,053評(píng)論 4 57
  • 從老家回來后俺陋,老公每天晚上都要找我聊天,這樣晚上 站樁總是在一邊聊天昙篙,一邊站樁中完成腊状,感覺到效果很是不好,不能全身...
    shanliyilvzuo閱讀 222評(píng)論 0 0
  • 一個(gè)流浪漢來到我家門前苔可,他想向母親要點(diǎn)吃的缴挖。這個(gè)流浪漢很可憐,他的右手連同整個(gè)手臂斷掉了焚辅,空空的衣袖晃蕩著映屋,讓人看...
    萬事從容閱讀 260評(píng)論 0 0