AsyncTask是android提供的輕量級的異步類,是針對子線程中更新UI,封裝簡化異步操作的封裝好的組件。Android的耗時操作如:網絡操作、讀取文件等如果放在主線程中會出現ANR(Application Not Responding)錯誤,使用AsyncTask可以保證Android的單線程模型,也避免了ANR。
構建AsyncTask子類的參數
AsyncTask<Params,Progress,Result>
是一個抽象類,通常用於被繼承,繼承AsyncTask需要指定如下三個泛型參數:
- Params: 啓動任務時輸入參數的類型
- Progress: 後臺執行任務中返回進度值的類型
- Result: 後臺執行任務完成後返回結果的類型
構建AsyncTask子類的回調方法
- doInBackground: 必須重寫,異步執行後臺線程將要完成的任務
- onPreExecute: 執行後臺耗時操作前被調用,通常用戶完成一些初始化操作
- onPostExecute: 當doInBackgroud()完成後,系統會自動調用onPostExecute()方法,並將doInBackgroud()方法返回的值傳給該方法
- onProgressUpdate: 在doInBackgroud()方法中調用publishProgress()方法
- doInBackground運行在子線程,其他方法都運行在主線程
注意事項
- 必須在UI線程中創建AsyncTask的實例
- 必須在UI線程中調用AsyncTask的execute()方法
- 重寫的四個方法是系統自動調用的,不應手動調用
- 每個AsyncTask只能被執行一次,多次調用將會引發異常
案例一:回調方法的執行順序
package com.example.asynctask;
import android.os.AsyncTask;
public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
System.out.println("=========doInBackground===========");
return null;
}
@Override
protected void onPreExecute() {
System.out.println("=========onPreExecute===========");
super.onPreExecute();
}
@Override
protected void onPostExecute(Void result) {
System.out.println("=========onPostExecute===========");
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Void... values) {
System.out.println("=========onProgressUpdate===========");
super.onProgressUpdate(values);//獲取進度值,更新進度條
}
}
執行結果爲:
在doInBackground中添加publishProgress()方法
@Override
protected Void doInBackground(Void... params) {
System.out.println("=========doInBackground===========");
publishProgress();//傳入進度值
return null;
}
執行結果爲:
案例二:加載一張網絡圖片
佈局文件activity_image.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="${relativePackage}.${activityClass}" >
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone" />
</RelativeLayout>
ImageActivity
package com.example.asynctask;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
public class ImageActivity extends Activity {
private ImageView mImageView;
private ProgressBar mProgressBar;
private static String URL = "https://img-my.csdn.net/uploads/avatar/6/A/7/1_leoleohan.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
mImageView = (ImageView) findViewById(R.id.image);
mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
// 設置傳遞進去的參數
new MyAsyncTask().execute(URL);
}
/**
* Params:啓動任務時輸入參數的類型,這裏傳入url,是String類型 ;Progress:後臺任務執行中返回進度值的類型。這裏填Void
* Result:後臺執行任務完成後返回結果的類型。這裏需要返回一個Bitmap
*
* @author LeoLeoHan
*
*/
class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);// 顯示控件
}
/**
* 獲取返回的結果,運行在主線程,所以可以對UI進行操作
*/
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
mProgressBar.setVisibility(View.GONE);
mImageView.setImageBitmap(bitmap);
}
/**
* 運行在子線程中,開始真正的異步操作
*/
@Override
protected Bitmap doInBackground(String... params) {
// String... params是可變長的數組,第0位就是傳進來的url
String url = params[0];
Bitmap bitmap = null;
// 定義網絡連接對象
URLConnection connection;
// 定義用於獲取數據的輸入流
InputStream is;
try {
connection = new URL(url).openConnection();
is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bitmap = BitmapFactory.decodeStream(bis);// 將輸入流解析成bitmap
is.close();
bis.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 將bitmap作爲參數返回
return bitmap;
}
}
}
案例三:模擬進度條
佈局文件activity_image.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:padding="16dp"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<ProgressBar
android:id="@+id/pg"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
</RelativeLayout>
ProgressBarActivity
package com.example.asynctask;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar;
public class ProgressBarActivity extends Activity {
private ProgressBar mProgressBar;
private MyAsyncTask myAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress_bar);
mProgressBar = (ProgressBar) findViewById(R.id.pg);
myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
}
@Override
protected void onPause() {
super.onPause();
if (myAsyncTask != null
&& myAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
// cancel方法只是將對應的asynctask標記爲cancel狀態,並不是真正的取消線程的執行
myAsyncTask.cancel(true);
}
}
class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... params) {
/**
* 模擬進度的更新
*/
for (int i = 0; i < 100; i++) {
if (isCancelled()) {
break;
}
publishProgress(i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (isCancelled()) {
return;
}
// 獲取進度更新值
mProgressBar.setProgress(values[0]);
}
}
}