Android AsyncTask的使用

AsyncTask方便我們在子線程進行耗時操作,並且方便切換到UI線程進行更新UI,不需要再使用Handler等在子線程與主線程之間進行通信了。

AsyncTask的基本用法

AsyncTask是一個抽象類,因此使用它就要寫一個類繼承它,繼承的時候需要指定三個泛型參數

  1. Params
    在執行後臺任務時需要傳入的參數類型,doInbackground()方法的參數
  2. Progress
    如果需要在界面上顯示執行的任務進度,則使用這裏指定的泛型指定的類型作爲進度單位,onProgressUpdate()方法和publishProgress()方法的參數
  3. Return
    任務執行完成後,如果需要返回值,就使用這裏指定的泛型作爲返回值的類型,doInbackground()方法的返回類型以及onPostExecute()方法的參數

重寫他的幾個方法,一個簡單的AsyncTask就可以寫成

class MyAsyncTask extends AsyncTask<Void, Integer, Boolean>{
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            // TODO Auto-generated method stub
            return null;
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
        }
        @Override
        protected void onPostExecute(Boolean result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
        }
    }

重寫的這四個方法爲

  1. onPreExecute()
    這個方法會在任務開始前進行調用,在這裏可以執行一些準備工作,例如顯示一個進度條等。
  2. doInbackground(Void…params)
    執行任務的方法,這個方法是在子線程中執行的,因此可以執行一些耗時任務,執行完畢後需要用return語句進行返回,返回的類型就是繼承AsyncTask時定義的第三個參數,如果定義爲Void,則不需要返回,定義爲Integer,就返回Integer類型。注意,由於該方法是在子線程中執行的,因此不可以更新UI,如果需要更新UI,應該調用publishProgress(Progress…)方法完成。
  3. onProgressUpdate(Integer…values)
    當後臺任務中調用了publishProgress(Progress…)方法後,這個方法很快便會被調用,方法中的參數就是publishProgress(Progress)方法傳遞進來的參數,該方法可以利用傳遞進來的參數更新UI,例如更新進度條的進度。
  4. onPostExecute(Boolean…result)
    當後臺任務執行完畢,通過return語句進行返回後,該方法馬上會被調用,返回的結果作爲參數傳遞到該方法中。在該方法中可以進行UI操作,例如提示任務完成,關閉進度條等。

使用實例(後臺下載圖片,並顯示)

繼承AsyncTask,泛型分別爲URL,Integer,Boolean,說明下載任務需要傳遞一個URL參數,然後更新進度是Integer類型,返回結果是Boolean類型

class DownloadAsyncTask extends AsyncTask<URL, Integer, Boolean>

重寫onPreExecute方法

在這裏,定義了一個進度條,顯示在主界面

@Override
        //運行前的準備
        protected void onPreExecute() {

            dialog=new ProgressDialog(MainActivity.this);
            dialog.setTitle("下載進度");
            dialog.setMax(100);
            dialog.setCancelable(true);
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.show();
        }

重寫doInbackground方法

傳遞進來需要下載的Url地址,然後通過HttpURLConnection訪問網絡,通過IO流進行下載圖片,然後計算進度,由於圖片太小,下載的太快,所以我在這裏每讀取一次byte[1024],就使線程休眠100毫秒,沒讀取一次就計算一次進度,然後publishProgress方法通知更新進度條

    @Override
        protected Boolean doInBackground(URL... params) {
            HttpURLConnection connection=null;
            int contentLenth=0;
            try {
                connection=(HttpURLConnection) params[0].openConnection();
                connection.setConnectTimeout(4000);
                connection.setReadTimeout(4000);
                connection.setRequestMethod("GET");
                contentLenth=connection.getContentLength();
                File file=new File(getCacheDir()+"xu.jpg");
                InputStream in=connection.getInputStream();
                FileOutputStream out=new FileOutputStream(file);
                byte[] b=new byte[1024];
                int len=0;
                int totalSize=0;
                while((len=in.read(b))!=-1){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    out.write(b, 0, len);
                    totalSize+=len*100;
                    int progress=(totalSize/contentLenth);
                    publishProgress(progress);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            return true;
        }

重寫onProgressUpdate方法

通過publishProgress方法傳遞進來的進度更新進度條的進度。


        @Override
        protected void onProgressUpdate(Integer... values) {
            dialog.setProgress(values[0]);
        }

重寫onPostExecute方法

如果返回的是true,就顯示下載成功,並將圖片顯示出來通過BitmapFactory.decodeStream(file)方法得到一個Bitmap對象,然後顯示在ImageView中。

@Override
        protected void onPostExecute(Boolean result) {
            dialog.dismiss();
            if(result){
                Toast.makeText(MainActivity.this, "下載成功", Toast.LENGTH_LONG).show();
                File file=new File(getCacheDir()+"xu.jpg");
                Bitmap bitmap=null;
                try {
                    bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                mShowImageView.setImageBitmap(bitmap);

            }else{
                Toast.makeText(MainActivity.this, "下載失敗", Toast.LENGTH_LONG).show();
            }
        }

調用執行

界面一打開,就開始下載,然後完成後在ImageView上顯示


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mShowImageView=(ImageView) findViewById(R.id.main_show_ImageView);
        try {
            new DownloadAsyncTask().execute(new URL("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1465108635&di=d36b371b3eeb89bf304ccfbee2b4f1cd&src=http://picture.youth.cn/dmzb/201305/W020130514542662922703.jpg"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

運行結果

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

可以看到已經成功了,注意別忘了配置網絡訪問權限!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章