異步任務之AsyncTask實現<一>

分類:IT技術 時間:2016-10-11

轉發請註明出處:http://blog.csdn.net/qq_28055429/article/details/51934966

前言:因為handler+message來實現異步操作相對復雜,故而如果只需簡單異步操作的話,可用異步任務AsyncTask來實現

一,基本知識:

(1)原型:

android.os.AsyncTask<Params,Progress,Result> :
三個參數
Params --------啟動任務執行的輸入參數,比如HTTP請求的URL。
Progress -----後臺任務執行的百分比,。
Result --------後臺執行任務最終返回的結果,比如Drawable。


(2)基本步驟:

4個步驟:

onPreExecute():  執行後臺操作前回調的函數,常用來設置任務,例如:在用戶界面中顯示一個進度條。

doInBackground(Void... params) :後臺執行耗時的操作,常用於接受參數返回結果,結果返回到onPostExecute()中

不能直接操作UI,在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。

onProgressupdate(Progress...) : 在調用publishProgress(Progress... values)時,此方法被執行,直接將進度信息更新到UI組件上。

onPostExecute (String result):執行後臺操作完畢後自動回調此函數,後臺操作結束後的結果會返回到這裏,來使用

(3)基本方法:

boolean   cancel(boolean mayInterruptIfRunning)  :嘗試取消,如任務下載時,突然想停止,可設置XX.cancel(true);

execute(Params... params)       :根據參數來開始執行

get():如果有必要,就等待計算完成,然後取它的結果

get(long timeout, TimeUnit unit)  :如果有必要,等待規定時間的計算,然後取它的結果

boolean isCancelled()    :判斷操作是否已經取消了

 AsyncTask.Status  getStatus()  :獲取當前任務的狀態,

(4)4個原則:

1.異步任務的實例必須在UI線程中創建。

2.execute(Params... params)方法必須在UI線程中調用。

3.不要手動調用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)這幾個方法。

4.一個任務實例只能執行一次,如果執行第二次將會拋出異常。

(5)用法:一般都是一個類去繼承AsyncTask,重寫裏面的方法,一般重寫的方法有:doInBackground和onPostExecute

這是官方的例子:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
在MainActivity中執行代碼:

 new DownloadFilesTask().execute(url1, url2, url3);



二,例子:

例子(1):加載網絡圖片:

布局:activity_third:放置一個imageView用於顯示圖片

<?xml version="1.0" encoding="utf-8"?>
<!--定義基本布局:LinearLayout-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <!--定義一個imageView來顯示圖片-->
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:src=http://blog.csdn.net/qq_28055429/article/details/"@drawable/load"/>



異步類:ImageAsyncTask:繼承自AsyncTask<Void , Void, Drawable>,實現其中的方法:


package testsdcard.com.maiyu.s04_79.domain;

import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ImageView;

import Java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import testsdcard.com.maiyu.s04_79.R;

/**自定義ImageAsynTask類,繼承自異步任務類
 * Created by maiyu on 2016/7/17.
 */
public class ImageAsynTask extends AsyncTask<Void ,Void ,Drawable> {
    private ImageView m ;       //用來顯示圖片
    private String imageUrl ;   //記錄網絡圖片地址

    //根據imageView對象和網絡圖片網址的,構造函數
    public ImageAsynTask(ImageView i , String t){
        m  = i ;
        imageUrl = t ;
    }
    //後臺執行耗時的操作
    @Override
    protected Drawable doInBackground(Void... voids) {
        return loadImages(imageUrl);    //自定義加載圖片的方法
    }

    //執行後臺操作完畢後自動回調此方法
    @Override
    protected void onPostExecute(Drawable drawable) {
        super.onPostExecute(drawable);
        if(drawable != null){       //判斷圖片加載是否成功
            m.setImageDrawable(drawable);
        }else {
            m.setImageResource(R.drawable.failed);
        }
    }
    //執行後臺操作前的回調函數
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    //根據網址加載圖片
    private Drawable loadImages(String url) {
        try{
            //生成URL對象
            URL mUrl = new URL(url);
            //得到inputStream
            InputStream inputStream = (InputStream)mUrl.openStream();
            return Drawable.createFromStream(inputStream , "test"); //生成並返回圖片

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }
}

測試類:ThridActivity:在裏面主要新建異步任務來測試加載圖片:

new ImageAsynTask(mImage , "http://p4.so.qhimg.com/t01aade72dccf26cffe.jpg").execute();

代碼如下:


package testsdcard.com.maiyu.s04_79.activity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;

import testsdcard.com.maiyu.s04_79.R;
import testsdcard.com.maiyu.s04_79.domain.ImageAsynTask;

/**
 * Created by maiyu on 2016/7/17.
 */
public class ThirdActivity extends Activity {
    private ImageView mImage ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        mImage = (ImageView)findViewById(R.id.imageView);
        //新建一個異步任務,開始加載網絡圖片
        new ImageAsynTask(mImage , "http://p4.so.qhimg.com/t01aade72dccf26cffe.jpg").execute();
    }
}

記得加網絡權限:
<uses-permission android:name="android.permission.Internet"></uses-permission>

結果:略,,,


例子2:根據網址下載網絡Html內容,可中斷下載,即測試類cancel(boolean)方法:

布局:activity_four:放置一個editText,兩個按鈕,即下載和停止,一個ScrollView(裏面放置一個TextView)用於顯示內容:

<?xml version="1.0" encoding="utf-8"?>
<!--定義當前的基本布局;LinearLayout-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <!--定義獲得用戶需要加載的網址的輸入框-->
    <EditText
        android:id="@+id/Et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/four_edt1"/>
    <!--定義用戶單擊開始加載按鈕控件-->
    <Button
        android:id="@+id/BtnStart"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/four_btn1"/>
    <!--定義用戶單擊終止加載按鈕控件-->
    <Button
        android:id="@+id/BtnStop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/four_btn2"/>
    <!--用於顯示內容-->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/Tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </ScrollView>

</LinearLayout>

異步類:HtmlAsyncTask繼承自AsyncTask<Void , Void, String>,再去實現裏面方法,

代碼如下:

package testsdcard.com.maiyu.s04_79.domain;

import java.io.IOException;

import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;

//自定義ImageAsynTask類,繼承自異步任務類
public class HtmlAsyncTask extends AsyncTask<Void, Void, String> {
    //用來存儲加載網址內容成功後展示網絡源代碼的TextView對象
    private TextView m;
    //記錄需要加載的網絡地址
    private String url;

    //構造函數,傳入TextView對象和網絡地址
    public HtmlAsyncTask(TextView i, String t) {
        m = i;
        url = t;
    }

    //後臺執行耗時的操作
    @Override
    protected String doInBackground(Void... params) {
        return requestByHttpGet(url);
    }

    //執行後臺操作完畢後自動回調此函數
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.e("isCancelled()", isCancelled() + "");
        //如果用戶取消此異步任務
        if (isCancelled()) {
            m.setText("取消加載");
        }
        //如果加載的得到的網絡地址的源代碼不為空的話,設置textview對象的值
        else if (null != result) {
            m.setText(result);
        }
        //如果加載的內容為空的話,顯示加載失敗
        else {
            m.setText("加載失敗");
        }
    }

    //執行後臺操作前回調的函數
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }


    //通過加載url的網絡內容
    public String requestByHttpGet(String url) {
        //新建HttpGet對象
        HttpGet httpGet = new HttpGet(url);
        //定義HttpClient對象
        HttpClient httpClient = new DefaultHttpClient();
        //定義HttpResponse實例
        HttpResponse httpResp;
        try {
            httpResp = httpClient.execute(httpGet);
            // 判斷是夠請求成功
            if (httpResp.getStatusLine().getStatusCode() == 200) {
                // 獲取返回的數據
                String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");
                Log.e("TAG", "HttpGet方式請求成功,返回數據如下:");
                return result;
            } else {
                Log.e("TAG", "HttpGet方式請求失敗");
            }
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

測試類:同理:代碼如下:

package testsdcard.com.maiyu.s04_79.activity;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import testsdcard.com.maiyu.s04_79.R;
import testsdcard.com.maiyu.s04_79.domain.HtmlAsyncTask;

//定義了本實例的主要Activity
public class FourActivity extends Activity {
    //定義布局中的TextView控件
    private TextView tv;
    //定義布局中的EditText控件
    private EditText et;
    //定義布局中的開始加載Button控件
    private Button btnstart;
    //定義布局中的終止加載Button控件
    private Button btnstop;
    //定義異步請求html代碼的異步任務
    protected HtmlAsyncTask hat;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findView();
        setListener();
    }

    private void setListener() {
        //設置btn的點擊監聽器
        btnstart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //初始textview的內容
                tv.setText("Html加載中.........");
                //獲取EditText的用戶輸入值
                String str = et.getText().toString();
                //啟動異步任務加載用戶輸入的url中的網絡html
                hat = new HtmlAsyncTask(tv, str);
                hat.execute();
            }
        });
        btnstop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //終止異步任務
                hat.cancel(true);
            }
        });
    }

    private void findView() {
        //得到布局中的TextView的對象
        tv = (TextView) findViewById(R.id.Tv);
        //得到布局中的EditText的對象
        et = (EditText) findViewById(R.id.Et);
        //得到布局中的開始加載的Button的對象
        btnstart = (Button) findViewById(R.id.BtnStart);
        //得到布局中的開始加載的Button的對象
        btnstop = (Button) findViewById(R.id.BtnStop);
    }
}


同樣要加網絡權限:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
結果:略,,


三,總結:

AsyncTask使用的一般步驟:

(1)創建一個類,繼承AsyncTask<參數1,參數2,參數3>,參數一般為<Void,Void,你想要返回的類型>,

如:ImageAsyncTask extends AsyncTask<Void ,Void ,Drawable>  {}//獲取圖片

StringAsyncTask extends AsyncTask<Void ,Void ,String>{}//獲取字符串數據

(2)然後去重寫其中的方法,一般重寫的有doInBackground和onPostExecute

如:略,,,

(3)在測試類中去調用,並執行execute()方法。

   上一個例子中:

new HtmlAsyncTask(tv, str).execute();





Tags: message cancel result values 百分比

文章來源:


ads
ads

相關文章
ads

相關文章

ad