Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android_AsyncTask

Android_AsyncTask

編輯:關於Android編程

一.AsyncTask的簡介

在Android中實現異步任務機制有兩種方式,Handler和AsyncTask。
Handler模式需要為每一個任務創建一個新的線程,任務完成後通過Handler實例向UI線程發送消息,完成界面的更新,這種方式對於整個過程的控制比較精細,但也是有缺點的,例如代碼相對臃腫,在多個任務同時執行時,不易對線程進行精確的控制。關於Handler的相關知識,前面也有所介紹,不清楚的朋友們可以參照一下。為了簡化操作Android1.5提供了工具類android.os.AsyncTask,它使創建異步任務變得更加簡單,不再需要編寫任務線程和Handler實例即可完成相同的任務。

AsyncTask,即異步任務,是Android給我們提供的一個處理異步任務的類.通過此類,可以實現UI線程和後台線程進行通訊,後台線程執行異步任務,並把結果返回給UI線程.

我通常會把代碼的邏輯想成現實生活中的某些現象,加以理解!以前的博客的都沒有把這類想法寫在博客,是怕誤導別人!以後的博客我會加上這部分,僅僅是為了自己的回憶和理解!

AsyncTask,為什麼需要這個東西呢?

因為每個程序就只有一個主線程,就像我們公司中某個項目的項目管理者,負責展示項目(顯示UI)等操作,可是他不可能一個人做完一整個項目,需要其他人的幫忙做其他的事情,這也就好比是線程了!讓線程去做一些耗時的操作,然後做完就告訴項目負責人,做完了,可以更新我們的項目了(更新UI)!那幫忙做事的人也不可能就一個人,一個人的效率太低了,可能已一隊人,也就是線程池了!AsyncTask也就是把這一麻煩的過程給封裝好了,可以理解為AsyncTask是這個過程規范!

二.AsyncTask的方法

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

構建AsyncTask子類的回調方法
AsyncTask主要有如下幾個方法:
doInBackground:必須重寫,異步執行後台線程要完成的任務,耗時操作將在此方法中完成.
onPreExecute:執行後台耗時操作前被調用,通常用於進行初始化操作.
onPostExecute:當doInBackground方法完成後,系統將自動調用此方法,並將doInBackground方法返回的值傳入此方法.通過此方法進行UI的更新.
onProgressUpdate:當在doInBackground方法中調用publishProgress方法更新任務執行進度後,將調用此方法.通過此方法我們可以知曉任務的完成進度.

三.示例

演示一個典型的異步處理的實例--加載網絡圖片.網絡操作作為一個不穩定的耗時操作,從4.0開始就被嚴禁放入主線程中.所以在顯示一張網絡圖片時,我們需要在異步處理中下載圖片,並在UI線程中設置圖片。

代碼中主要是onPreExecute,doInBackground,onPostExecute方法中進行操作,我們可以理解為:項目的負責人發布了一項任務,需要完成,因此他用AsyncTask這個規范去執行(execute()),任何的任務都基本是三個部分,事前准備(onPreExecute),執行工作(doInBackground),完成結果(onPostExecute)!

好了,看下界面效果和代碼,自己聯想下!

還有一點,這裡用到網絡操作,記得加權限喔!

\

 

 

package com.liangdianshui.asynctaskdemo;

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;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class DownloadImageActivity extends Activity {

	private ProgressBar mProgress;
	private ImageView mIvDownloadImage;
	private static String Url ="http://img5.imgtn.bdimg.com/it/u=794383953,3828916890&fm=21&gp=0.jpg";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_download_image);
		initView();
		new MyAsyncTask().execute(Url);
	}

	private void initView() {
		mProgress = (ProgressBar) findViewById(R.id.progress);
		mIvDownloadImage = (ImageView) findViewById(R.id.iv_image_download);
	}

	/**
	 * Params:啟動任務時輸入的參數類型. doInBackground()
	 * Progress:後台任務執行中返回進度值的類型.onProgressUpdate()
	 * Result:後台任務執行完成後返回結果的類型.onPostExecute()
	 */
	class MyAsyncTask extends AsyncTask {

		//進行異步任務的處理.
		@Override
		protected Bitmap doInBackground(String... params) {
			//獲取傳進來的第一個參數
			String url = params[0];
			Bitmap bitmap = null;
			try {
				/**
				 * No address associated with hostname
				 * 報上面的錯誤原因:1.沒有設置連網的權限  2.手機沒開網絡
				 */
				//打開鏈接
				URLConnection urlConnection = new URL(url).openConnection();
				InputStream inputStream = urlConnection.getInputStream();
				BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
				//為了更清楚的顯示,在線程休眠3s
				Thread.sleep(3000);
				bitmap = BitmapFactory.decodeStream(bufferedInputStream);
				//記得關閉流
				bufferedInputStream.close();
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return bitmap;
		}

		//異步處理前的操作
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			//將ProgressBar設置為可見的
			mProgress.setVisibility(View.VISIBLE);
		}

		//異步處理後的操作
		//bitmap是doInBackground操作後返回的值
		@Override
		protected void onPostExecute(Bitmap bitmap) {
			super.onPostExecute(bitmap);
			//操作完成後把進程顯示隱藏,並把異步下載的圖片顯示在ImageView中
			mProgress.setVisibility(View.GONE);
			mIvDownloadImage.setImageBitmap(bitmap);
		}
	}
}

 

 

第二個示例是“加載進條”

我們看下示例的效果吧:

\

這裡看起來好像沒啥問題啊,可是仔細看,你會發現,當加載進度條加載到一半的時候,你按返回鍵,再加載進度條,你會發現,要等待一段時間才會加載!這是為什麼呢?

因為:AsyncTask是基於線程池進行實現的,當一個線程沒有結束時,後面的線程是不能執行的.所以必須等到第一個task的for循環結束後,才能執行第二個task.我們知道,當點擊BACK鍵時會調用Activity的onPause()方法.為了解決這個問題,我們需要在Activity的onPause()方法中將正在執行的task標記為cancel狀態,在doInBackground方法中進行異步處理時判斷是否是cancel狀態來決定是否取消之前的task.

這就好像是項目的負責人,發布了一項任務,那一隊人就在干這項任務(線程池執行操作,也就是doInBackground方法的操作),好了今天做到一半,明天上班上班,會繼續干這個任務,而不會停下來,重新執行這個任務或者干另一個任務!因為他沒有接收到負責人的命令!因此當按了返回鍵的時候,我們再點擊加載進度條,項目的負責人需要告訴他們這個項目暫時不做了(也就是把執行的task標記為cancel狀態),然後工人就判斷這個任務是否有這個狀態,有這個狀態就停止不干了!

加上了cancel後的效果圖是這樣的:

\

 

代碼:

 

package com.liangdianshui.asynctaskdemo;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar;

public class ProgressActivity extends Activity {

	private ProgressBar mProgress;
	private MyAsyncTask mAsyncTask;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_progress);
		mProgress = (ProgressBar) findViewById(R.id.pro_show_progress);
		mAsyncTask=new MyAsyncTask();
		mAsyncTask.execute();
	}

	class MyAsyncTask extends AsyncTask {
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mProgress.setProgress(0);
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			mProgress.setProgress(values[0]);
		}

		@Override
		protected void onPostExecute(Void aVoid) {
			super.onPostExecute(aVoid);
		}

		@Override
		protected Void doInBackground(Void... params) {
			for (int i = 0; i < 100; i++) {
				//如果task是cancel狀態,則終止for循環
				if (isCancelled()) {
					break;
				}
				//調用publishProgress方法將自動觸發onProgressUpdate方法,把參數傳進去,來進行進度條的更新.
				publishProgress(i);
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			return null;
		}
	}

	;

	@Override
	protected void onPause() {
		super.onPause();
		if (mAsyncTask != null && mAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
			//cancel方法只是將對應的AsyncTask標記為cancelt狀態,並不是真正的取消線程的執行.
			mAsyncTask.cancel(true);
		}
	}
}

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved