1. 程式人生 > >Java多執行緒之非同步任務——AsyncTask

Java多執行緒之非同步任務——AsyncTask

為什麼需要非同步任務?
1、Android單執行緒模型
2、耗時操作放在非主執行緒中執行

AsyncTask為何而生?
1、子執行緒中更新UI
2、封裝、簡化非同步操作

構建AsyncTask子類的引數
AsyncTask<Params,Progress,Result>是一個抽象類,通常用於被繼承,繼承AsyncTask需要制定如下三個泛型引數:
Params:啟動任務是輸入引數的型別。
Progress:後臺任務執行中返回進度值的型別。
Result:後臺執行任務完成後返回結果的型別。


構建AsyncTask子類的回撥方法:
doInBackground:
必須重寫,非同步執行後臺執行緒將要完成的任務;
onPreExecute:
執行後臺耗時操作前呼叫,通常使用者完成一些初始化操作;
onPostExecute:當doInBackground()完成後,系統會自動呼叫onPostExecute()方法,並將doInBackground()方法返回的值傳給該方法;
onProgressUpdate:在doInBackground()方法中呼叫publishProgress()方法更新任務的執行進度後,就會觸發該方法。

回撥方法的執行順序:
onPreExecute() -> doInBackground() -> onPostExecute()

在doInBackground()方法中呼叫publishProgress()方法更新任務的執行進度:

onPreExecute() -> doInBackground() -> onProgressUpdate() -> onPostExecute()

完成初始化操作       完成耗時操作              更新進度條                得到doInBackground的返回值進行處理

接下來新建一個Android專案測試一下,新建Android專案之後,直接新增一個MyAsyncTask類:

public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
	private static final String TAG = "MyAsyncTask";

	@Override
	protected Void doInBackground(Void... arg0) {
		Log.e(TAG, "****doInBackground****");
		publishProgress();
		return null;
	}

	@Override
	protected void onPostExecute(Void result) {
		Log.e(TAG, "****onPostExecute****");
		super.onPostExecute(result);
	}

	@Override
	protected void onPreExecute() {
		Log.e(TAG, "****onPreExecute****");
		super.onPreExecute();
	}

	@Override
	protected void onProgressUpdate(Void... values) {
		Log.e(TAG, "****onProgressUpdate****");
		super.onProgressUpdate(values);
	}

	
}

而後在MainActivity.java裡面new一個MyAsyncTask類,並呼叫execute()方法:
public class MainActivity extends ActionBarActivity {


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		MyAsyncTask task = new MyAsyncTask();
		task.execute();
	}
	
}

執行檢視Log列印情況:


根據列印的Log,我們可以發現四個方法的執行順序。

接下來我們修改一下並繼續編寫專案,簡單的使用一下AsyncTask。

MyAsyncTask類:

public class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {
	private static final String TAG = "MyAsyncTask";
	private ImageView imageView;
	
	public MyAsyncTask(ImageView imageView){
		this.imageView = imageView;
	}
	
	@Override
	protected Bitmap doInBackground(String... arg0) {
		Log.e(TAG, "****doInBackground****");
		publishProgress();
		//獲取傳遞進來的引數
		String url = arg0[0];
		Bitmap bitmap = null;
		URLConnection connection;
		InputStream is;
		
		try {
			connection = new URL(url).openConnection();
			is = connection.getInputStream();
			BufferedInputStream bis = new BufferedInputStream(is);
			//通過decodeStream解析輸入流
			bitmap = BitmapFactory.decodeStream(bis);
			is.close();
			bis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//將Bitmap作為返回值
		return bitmap;
	}

	@Override
	protected void onPostExecute(Bitmap bitmap) {
		Log.e(TAG, "****onPostExecute****");
		imageView.setImageBitmap(bitmap);
		super.onPostExecute(bitmap);
	}

	@Override
	protected void onPreExecute() {
		Log.e(TAG, "****onPreExecute****");
		super.onPreExecute();
	}

	@Override
	protected void onProgressUpdate(Void... values) {
		Log.e(TAG, "****onProgressUpdate****");
		super.onProgressUpdate(values);
	}

	
}

MainActivity類:

public class MainActivity extends ActionBarActivity {
	private final String URL = "https://www.baidu.com/img/bd_logo1.png";
	private ImageView imageView1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		imageView1 = (ImageView) findViewById(R.id.imageView1);
		MyAsyncTask task = new MyAsyncTask(imageView1);
		task.execute(URL);
	}
	
}

activity_main.xml佈局檔案:

<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="com.itman.asynctaskdemo.MainActivity" >


    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher" />

</RelativeLayout>

別忘記新增網路訪問許可權,最後執行專案,結果如下圖:




非同步任務---AsyncTask使用的注意事項:
1、必須在UI執行緒中建立AsyncTask的例項
2、必須在UI執行緒中呼叫AsyncTask的execute()方法
3、重寫的四個方法是系統自動呼叫的,不應手動呼叫
4、每個AsyncTask只能被執行一次,多次呼叫將會引發異常(尤其注意