Android異步任務(wù)-AsyncTask

之前簡(jiǎn)單的介紹了Android-Handler的消息傳遞機(jī)制可缚,其中計(jì)算質(zhì)數(shù)的demo在利用子Handler去計(jì)算和更新TextView的時(shí)候顯的十分復(fù)雜作谚。其實(shí)Android還提供了另外一種簡(jiǎn)化的方法叫異步任務(wù)(AsyncTask)怕篷;相對(duì)來說AsyncTask更輕量級(jí)一些捶朵,適用于簡(jiǎn)單的異步處理括荡。

我們來看看利用AsyncTask進(jìn)行開發(fā)后的計(jì)算質(zhì)數(shù)demo,Java代碼如下:

public class AsyncTaskActivity extends AppCompatActivity {
    private TextView tv_calculate_result;
    private EditText edit_number;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        tv_calculate_result = (TextView) findViewById(R.id.tv_calculate_result);
        edit_number = (EditText) findViewById(R.id.edit_number);
        findViewById(R.id.btn_calculate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (TextUtils.isEmpty(edit_number.getText().toString().trim())) {
                    Toast.makeText(AsyncTaskActivity.this, "請(qǐng)輸入數(shù)字", Toast.LENGTH_SHORT).show();
                } else {
                    CalculateTask calculateTask = new CalculateTask();
                    calculateTask.execute(edit_number.getText().toString().trim());
                }
            }
        });
    }

    private class CalculateTask extends AsyncTask<String,Integer,String>{


        @Override
        protected String doInBackground(String... params) {
            int upper = Integer.parseInt(params[0]);
            List<Integer> nums = new ArrayList<>();
            //計(jì)算從2開始脉课,到upper的所有質(zhì)數(shù)
            outer:
            for (int i = 2; i <= upper; i++) {
                //用i除以從2開始,到i的平方根的所有數(shù)
                for (int j = 2; j <= Math.sqrt(i); j++) {
                    //如果可以整除财异,則表明這個(gè)數(shù)不是質(zhì)數(shù)
                    if (i != 2 && i % j == 0) {
                        continue outer;
                    }
                }
                nums.add(i);
            }
            return nums.toString();
        }

        @Override
        protected void onPostExecute(String s) {
            tv_calculate_result.setText(s);
        }
    }
}

運(yùn)行效果:

計(jì)算質(zhì)數(shù).gif

對(duì)于AsyncTask我們主要重寫了doInBackground()和onPostExecute()兩個(gè)方法就解決了我們之前的問題倘零。

AsyncTask<Params, Progress, Result>抽象類

AsyncTask<Params, Progress, Result>是一個(gè)抽象類,通常用于被繼承戳寸,繼承時(shí)需要指定一下三個(gè)泛型參數(shù)呈驶。

  • Params:?jiǎn)?dòng)任務(wù)執(zhí)行的輸入?yún)?shù)的類型。
  • Progress:后臺(tái)任務(wù)完成的進(jìn)度值類型疫鹊。
  • Result:后臺(tái)執(zhí)行任務(wù)完成后返回結(jié)果的類型袖瞻。

如何使用AsyncTask

使用AsyncTask只要三步即可。

  1. 創(chuàng)建AsyncTask的子類拆吆,并為三個(gè)泛型參數(shù)指定類型聋迎。如果某個(gè)不需要指定就設(shè)置為Void。
  2. 根據(jù)需要锈拨,實(shí)現(xiàn)AsyncTask的如下方法砌庄。

doInBackground(Params...):后臺(tái)線程將要完成的任務(wù)。該方法可以調(diào)用publishProgress(Progress... values)方法更新任務(wù)的執(zhí)行進(jìn)度。
onProgressUpdate(Progress... values):在doInBackground()中調(diào)用publishProgress()方法更新任務(wù)的執(zhí)行進(jìn)度后會(huì)觸發(fā)該方法娄昆。
onPreExecute():執(zhí)行后臺(tái)耗時(shí)操作前調(diào)用佩微。通常用于完成一些初始化的準(zhǔn)備工作,比如在界面上顯示進(jìn)度條等萌焰。
onPostExecute(Result result):當(dāng)doInBackground()完成后哺眯,系統(tǒng)會(huì)自動(dòng)調(diào)用此方法并將doInBackground()的返回值傳給該方法。

  1. 調(diào)用AsyncTask子類的實(shí)例的execute(Params... params)開始執(zhí)行耗時(shí)任務(wù)。

使用AsyncTask要遵守的規(guī)則

  • 必須在UI線程中創(chuàng)建AsyncTask的實(shí)例街州;
  • 必須在UI線程中調(diào)用AsyncTask的execute()方法活尊。
  • AsyncTask的doInBackground(Params...)、onProgressUpdate(Progress... values)夺姑、onPreExecute()、onPostExecute(Result result)方法掌猛,不應(yīng)該有程序員代碼調(diào)用盏浙,而是Android系統(tǒng)負(fù)責(zé)調(diào)用。
  • 每個(gè)AsyncTask只能被執(zhí)行一次荔茬,多次調(diào)用會(huì)引發(fā)異常废膘。

以下是一個(gè)使用異步任務(wù)執(zhí)行下載的實(shí)例,代碼如下:

public class AsyncTaskActivity extends AppCompatActivity {
    private TextView tv_show;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        tv_show = (TextView) findViewById(R.id.tv_show);
        findViewById(R.id.btn_down).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DownTask downTask = new DownTask(AsyncTaskActivity.this);
                try {
                    downTask.execute(new URL("http://www.reibang.com/p/e807eb8c31f0"));
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private class DownTask extends AsyncTask<URL, Integer, String> {
        //可變長(zhǎng)的輸入?yún)?shù)慕蔚,與AsyncTask.execute()對(duì)應(yīng)
        ProgressDialog pdialog;
        //定義記錄已經(jīng)讀取的行數(shù)
        int hasRead = 0;
        Context mContext;

        public DownTask(Context ctx) {
            mContext = ctx;
        }

        @Override
        //后臺(tái)進(jìn)程將要完成的任務(wù)
        protected String doInBackground(URL... params) {
            StringBuilder sb = new StringBuilder();
            try {
                URLConnection conn = params[0].openConnection();
                //打開conn連接對(duì)應(yīng)的輸入流丐黄,并將它包裝成BufferedReader
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line).append("\n");
                    hasRead++;
                    publishProgress(hasRead);//更新任務(wù)的執(zhí)行進(jìn)度
                }
                return sb.toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        //當(dāng)doInBackground()完成后系統(tǒng)會(huì)自動(dòng)調(diào)用此方法并將doInBackground()的返回值傳給該方法
        protected void onPostExecute(String s) {
            //返回HTML頁面內(nèi)容
            tv_show.setText(s);
            pdialog.dismiss();
        }

        @Override
        //執(zhí)行后臺(tái)耗時(shí)操作前被調(diào)用
        protected void onPreExecute() {
            pdialog = new ProgressDialog(mContext);
            pdialog.setTitle("正在下載...");
            pdialog.setMessage("任務(wù)正在執(zhí)行中,請(qǐng)等待...");
            pdialog.setCancelable(false);
            pdialog.setMax(202);
            pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pdialog.setIndeterminate(false);//設(shè)置對(duì)話框的進(jìn)度條是否顯示進(jìn)度
            pdialog.show();
        }

        @Override
        //在doInBackground()中調(diào)用publishProgress()方法更新任務(wù)會(huì)觸發(fā)該方法
        protected void onProgressUpdate(Integer... values) {
            //更新進(jìn)度
            tv_show.setText("已讀取了【" + values[0] + "】行孔飒!");
            pdialog.setProgress(values[0]);
        }
    }
}

運(yùn)行效果:

下載網(wǎng)頁代碼.gif

參考文章

  • 《瘋狂android講義》(第3版)第3章3.6 異步任務(wù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灌闺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子十偶,更是在濱河造成了極大的恐慌菩鲜,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惦积,死亡現(xiàn)場(chǎng)離奇詭異接校,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狮崩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門蛛勉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人睦柴,你說我怎么就攤上這事诽凌。” “怎么了坦敌?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵侣诵,是天一觀的道長(zhǎng)痢法。 經(jīng)常有香客問我,道長(zhǎng)杜顺,這世上最難降的妖魔是什么财搁? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮躬络,結(jié)果婚禮上尖奔,老公的妹妹穿的比我還像新娘。我一直安慰自己穷当,他們只是感情好提茁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馁菜,像睡著了一般茴扁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上火邓,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天丹弱,我揣著相機(jī)與錄音,去河邊找鬼铲咨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蜓洪,可吹牛的內(nèi)容都是我干的纤勒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼隆檀,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼摇天!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恐仑,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤泉坐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后裳仆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腕让,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年歧斟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纯丸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡静袖,死狀恐怖觉鼻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情队橙,我是刑警寧澤坠陈,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布萨惑,位于F島的核電站,受9級(jí)特大地震影響仇矾,放射性物質(zhì)發(fā)生泄漏庸蔼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一若未、第九天 我趴在偏房一處隱蔽的房頂上張望朱嘴。 院中可真熱鬧,春花似錦粗合、人聲如沸萍嬉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壤追。三九已至,卻和暖如春供屉,著一層夾襖步出監(jiān)牢的瞬間行冰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工伶丐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悼做,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓哗魂,卻偏偏與公主長(zhǎng)得像肛走,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子录别,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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