轉發請註明出處: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 百分比
文章來源: