android:異步任務asyncTask介紹及異步任務下載圖片(帶進度條)

WarnerOBrie 8年前發布 | 21K 次閱讀 Java開發

來自: http://blog.csdn.net/su20145104009/article/details/50759618


為什么要用異步任務?

在android中只有在主線程才能對ui進行更新操作,而其它線程不能直接對ui進行操作

android本身是一個多線程的操作系統,我們不能把所有的操作都放在主線程中操作 ,比如一些耗時操作。如果放在主線程中 會造成阻塞 而當阻塞事件過長時 系統會拋出anr異常。所以我們要使用異步任務。android為我們提供了一個封裝好的組件asynctask。

AsyncTask可以在子線程中更新ui,封裝簡化了異步操作。適用于簡單的異步處理。如果多個后臺任務時就要使用Handler了 在這里就不再說明。

AsyncTask通常用于被繼承。AsyncTask定義了三種泛型類型<Params,Progress,Result>

Params:啟動任務時輸入的參數類型

Progress:后臺任務執行的百分比

Result:執行任務完成后返回結果的類型

繼承AsyncTask后要重寫的方法有:

doInBackgroud:必須重寫,異步執行后臺線程要完成的任務,耗時任務要寫在這里,并且在這里不能操作ui。可以調用 publishProgress方法來更新實時的任務進度

onPreExecute:執行耗時操作前調用,可以完成一些初始化操作

onPostExecute:在doInBackground 執行完成后,主線程調用此方法,可以在此方法中操作ui

onProgressUpdate:在doInBackgroud方法中調用publishProgress方法,更新任務的執行進度后 就會調用這個方法

下面通過一個實例來了解AsyncTask

首先附上運行結果


布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btn_download"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="點擊下載" />

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <ImageView
            android:id="@+id/iv_image"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitCenter" />

    </FrameLayout>

</LinearLayout>
MainActivity

package com.example.asynctask;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URLConnection;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity implements OnClickListener{

    private ImageView image;
    private ProgressDialog progress;
    private Button btn_download;
    private static String URL="http://img4.imgtn.bdimg.com/it/u=1256159061,743487979&fm=21&gp=0.jpg";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        image=(ImageView) findViewById(R.id.iv_image);
        btn_download=(Button) findViewById(R.id.btn_download);
        progress=new ProgressDialog(this);
        progress.setIcon(R.drawable.ic_launcher);
        progress.setTitle("提示信息");
        progress.setMessage("正在下載,請稍候...");
        progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        btn_download.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        new MyAsyncTask().execute(URL);
    }
    /*
     * String*********對應我們的URL類型
     * Integer********進度條的進度值
     * BitMap*********異步任務完成后返回的類型  
     * */
    class MyAsyncTask extends AsyncTask<String, Integer, Bitmap>{

        //執行異步任務(doInBackground)之前執行,并且在ui線程中執行
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            if(image!=null){
                image.setVisibility(View.GONE);
            }
            //開始下載 對話框進度條顯示
            progress.show();
            progress.setProgress(0);
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            // TODO Auto-generated method stub
            //params是一個可變長的數組 在這里我們只傳進來了一個url 
            String url=params[0];
            Bitmap bitmap=null;
            URLConnection connection;
            InputStream is;//用于獲取數據的輸入流
            ByteArrayOutputStream bos;//可以捕獲內存緩沖區的數據,轉換成字節數組。
            int len;
            float count=0,total;//count為圖片已經下載的大小 total為總大小
            try {
                //獲取網絡連接對象
                connection=(URLConnection) new java.net.URL(url).openConnection();
                //獲取當前頁面的總長度
                total=(int)connection.getContentLength();
                //獲取輸入流
                is=connection.getInputStream();
                bos=new ByteArrayOutputStream();
                byte []data=new byte[1024];
                while((len=is.read(data))!=-1){
                    count+=len;
                    bos.write(data,0,len);
                    //調用publishProgress公布進度,最后onProgressUpdate方法將被執行
                    publishProgress((int)(count/total*100));
                    //為了顯示出進度 人為休眠0.5秒
                    Thread.sleep(500);
                }
                bitmap=BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.toByteArray().length);
                is.close();
                bos.close();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return bitmap;
        }
        //在ui線程中執行 可以操作ui
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            // TODO Auto-generated method stub
            super.onPostExecute(bitmap);
            //下載完成 對話框進度條隱藏
            progress.cancel();
            image.setImageBitmap(bitmap);
            image.setVisibility(View.VISIBLE);
        }

        /*
         * 在doInBackground方法中已經調用publishProgress方法 更新任務的執行進度后
         * 調用這個方法 實現進度條的更新
         * */
        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
            progress.setProgress(values[0]);
        }
    }
}

最后不要忘記在AndroidManifest文件中配置網絡訪問權限

<uses-permission android:name="android.permission.INTERNET"/>


 本文由用戶 WarnerOBrie 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!