AsyncTask基礎(chǔ)理解

AsyncTask

封裝好的異步消息處理機制

屬于抽象類,需要創(chuàng)建子類繼承AsyncTask。

開啟子線程執(zhí)行耗時任務(wù),實現(xiàn)子線程和主線程之間的通信,完成主線程的UI更新操作。

優(yōu)點

  • 方便實現(xiàn)異步通信
  • 采用線程池的緩存線程和復(fù)用線程,避免頻繁創(chuàng)建銷毀線程帶來的系統(tǒng)資源開銷。

AsyncTask實現(xiàn)類

public abstract class AsyncTask<Params,Progress,Result>{

}

三個泛型參數(shù)的意義:

  • Params:開始異步任務(wù)執(zhí)行時傳入給后臺的的參數(shù)類型。
  • Progress:任務(wù)執(zhí)行過程中,下載進度顯示單位的數(shù)據(jù)類型。
  • Result:異步任務(wù)執(zhí)行完成后,返回的結(jié)果類型。

常用方法

execute(Params param)

在主線程中觸發(fā)執(zhí)行異步線程任務(wù)。

onPreExecute()

在execute()錢自動調(diào)用,用處界面初始化操作,比如顯示一個進度條對話框。

doInBackground(Params params)

該方法內(nèi)所有代碼都在子線程中運行,處理耗時任務(wù),任務(wù)完成通過return語句將任務(wù)的執(zhí)行結(jié)果返回,如果AsyncTask
第三個泛型參數(shù)是Void,可以不返回任務(wù)執(zhí)行結(jié)果。該方法不可以進行UI操作。

onProgressUpdate(Progress values)

后臺任務(wù)調(diào)用publishProgress(Progress)方法后,該方法自動調(diào)用,在該方法內(nèi)可以對UI進行操作。

onPostExcute(Result result)

后臺任務(wù)執(zhí)行完畢并通過return語句進行返回是,該方法自動調(diào)用。利用返回的數(shù)據(jù)進行UI操作,比如提醒任務(wù)執(zhí)行的結(jié)果,關(guān)閉進度條對話框等。

onCancelled()

取消狀態(tài)并非真正的取消任務(wù),該方法執(zhí)行后,onPostExecute()方法就不會被調(diào)用。

定義子類

private class MyTask extends AsyncTask<Params, Progress, Result> {

   
      @Override
      protected void onPreExecute() {
           //線程任務(wù)前的初始化操作
        }

 
      @Override
      protected String doInBackground(String... params) {

            // 自定義的線程任務(wù)

            // 可調(diào)用publishProgress()顯示進度, 之后將執(zhí)行onProgressUpdate()
             publishProgress(count);
              
         }

  
      @Override
      protected void onProgressUpdate(Integer... progresses) {
               // 在主線程 顯示線程任務(wù)執(zhí)行的進度

        }

    
      @Override
      protected void onPostExecute(String result) {

         // UI操作

        }

    
      @Override
        protected void onCancelled() {
        
        }
  }

  //創(chuàng)建實例
  MyTask mTask = new MyTask();

  //執(zhí)行任務(wù)
  mTask.execute();

舉個例子

public class MainActivity extends AppCompatActivity{

    private static String TAG = "MainActivity";

    private TextView showText;

    private Button startButton;

    private Button cancelButton;

    private ProgressBar progressBar;

    private MyTask myTask = new MyTask();

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showText =(TextView)findViewById(R.id.text);
        progressBar = (ProgressBar)findViewById(R.id.progress_bar);
        startButton = (Button)findViewById(R.id.start_button);
       startButton.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {
    //同一個AsyncTask實例對象只能執(zhí)行1次,若執(zhí)行第2次將會拋出異常
            myTask.execute();
           }
       });
       cancelButton = (Button)findViewById(R.id.cancel_button);
       cancelButton.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View view) {
        myTask.cancel(true);
           }
       });

    }


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

        @Override
        protected void onPreExecute(){

            showText.setText("加載中");
        }

        @Override
        protected String doInBackground(String...params){

            try{
                int count = 0 ;
                int length = 1;
                while(count<99){
                    count += length;
                    //調(diào)用publishProgress()顯示進度,之后執(zhí)行onProgressUpdate()
                    publishProgress(count);

                    Thread.sleep(50);
                }

            }catch(InterruptedException e){
                e.printStackTrace();
            }

            return null;
        }

        //  主線程顯示執(zhí)行進度
        @Override

        protected void onProgressUpdate(Integer...progresses){

            progressBar.setProgress(progresses[0]);
            showText.setText("loading...."+progresses[0]+"%");


        }

        // 任務(wù)執(zhí)行結(jié)果
        @Override
        protected void onPostExecute(String result){
            showText.setText("加載完成");
        }

        //取消加載
        @Override
        protected void onCancelled(){

            showText.setText("取消加載");
            progressBar.setProgress(0);
        }
    }

}

注意點

生命周期

結(jié)論
AsyncTask不與任何組件綁定生命周期
使用建議
在Activity 或 Fragment中使用 AsyncTask時,最好在Activity 或 Fragment的onDestory()調(diào)用 cancel(boolean);

內(nèi)存泄漏

結(jié)論

若AsyncTask被聲明為Activity的非靜態(tài)內(nèi)部類,當Activity需銷毀時,會因AsyncTask保留對Activity的引用 而導(dǎo)致Activity無法被回收,最終引起內(nèi)存泄露

使用建議

AsyncTask應(yīng)被聲明為Activity的靜態(tài)內(nèi)部類

線程任務(wù)執(zhí)行結(jié)果 丟失

結(jié)論

當Activity重新創(chuàng)建時(屏幕旋轉(zhuǎn) / Activity被意外銷毀時后恢復(fù)),之前運行的AsyncTask(非靜態(tài)的內(nèi)部類)持有的之前Activity引用已無效,故復(fù)寫的onPostExecute()將不生效,即無法更新UI操作

使用建議

在Activity恢復(fù)時的對應(yīng)方法 重啟 任務(wù)線程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • Android開發(fā)者:你真的會用AsyncTask嗎? 導(dǎo)讀.1 在Android應(yīng)用開發(fā)中,我們需要時刻注意保證...
    cxm11閱讀 2,730評論 0 29
  • Android Handler機制系列文章整體內(nèi)容如下: Android Handler機制1之ThreadAnd...
    隔壁老李頭閱讀 3,271評論 1 15
  • AsyncTask 是一個簡單實用的多線程異步任務(wù)工具類。 Android 開發(fā)中經(jīng)常遇到需要將耗時的操作放到子線...
    HJDaryl閱讀 743評論 0 1
  • 一 “阿婆,你的名字是什么?” 她瞇著眼看著電視,手指挑撥著毛線,卻一...
    樹下不安生閱讀 310評論 0 0
  • 1.沖破自我意識的束縛。要在聽眾面前自然、流暢地講演的確不是一件容易的事,你必須進行多次的練習,才能達到這種境界。...
    貓小哚閱讀 329評論 0 0