异步任务AsyncTask

Android是单线程模型,耗时操作应放在非主线程中执行,故需要异步任务

AsyncTask可以使子线程中更新UI,封装、简化异步操作

构建AsyncTask子类的参数

AsyncTask<Params, Progress, Result>是一个抽象类,通常用于被继承,继承AsyncTask需要制定三个泛型参数:

Params:启动任务时输入参数的类型

Progress:后台任务执行中返回进度值的类型

Result:后台执行任务完成后返回结果的类型

构建AsyncTask子类的回调方法:

doInBackground:必须重写,异步执行后台线程将要完成的任务,其他的 方法并不是必须的

onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化操作

onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法返回的值传给该方法

onProgressUpdate:在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,就会触发该方法,获取进度,更新进度条

其中调用顺序是: onProExecute()-->doInBackground()-->onPostExecute()

若在doInBackground()中调用publishProgress()方法时,调用顺序是:onProExecute()-->doInBackground()-->onProgressUpdate()-->onPostExecute()

加载网络图片的实例:

异步处理-->下载图像

UI线程-->设置图像

public class ImageTest extends Activity{
	private ImageView mImageView;
	private ProgressBar mProgressBar;
	private static String URI = "http://pic4.nipic.com/20091121/3764872_215617048242_2.jpg";
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		setContentView(R.layout.image);
		mImageView = (ImageView)findViewById(R.id.image);
		mProgressBar = (ProgressBar)findViewById(R.id.progressbar);
		new MyAsyncTask().execute(URL);   //设置传递进的参数
	}

	class MyAsyncTask extends AsyncTask<String, void, Bitmap>{
		//<url类型, 进度值类型,返回值类型>
		
		protected void onPreExecute(){
			super.onPreExecute();
			mProgressBar.setVisibility(View.VISIBLE);  //显示进度条
		}

		protected Bitmap onPostExecute(Bitmap bitmap){
			super.onPostExecute(bitma);
			//操作UI,设置图像
			mProgressBar.setVisibility(View.GONE);
			mImageView.setImageBitmap(bitmap);
		}

		protected Bitmap doInBackground(String... params){
			String url = params[0]; //取出对应的URL
			Bitmap bitmap = null;
			URLConnection connection;
			InputStream is;
			try{
				connection = new URL(url).openConnection();
				is = connection.getInputStream();
				BufferedInputStream bis = new BufferedInputStream(is);
				Thread.sleep(3000);   //为了使加载的效果更明显,人为限制一下
				//通过decodeStream解析输入流
				bitmap = BitmapFactory.decodeStream(bis);
				is.close();	//注意关闭输入输出流
				bis.close();
			}catch(IOException e){
				e.printStackTrace();
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			//将bitmap返回
			return bitmap;
		}
	}
}


模拟进度条的实现:

public class ProgressBarTest extends Activity{
	private ProgressBar mProgressBar;
	private MyAsyncTask mTask;

	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		setContentView(R.layout.progressbar);
		mProgressBar = (ProgressBar)findViewById(R.id.pg);
		mTask = new MyAsyncTask();
		mTask.execute();
	}

	class MyAsyncTask extends AsyncTask<Void, Integer, Void>{
		protected Void doInBackground(Void... params){
			//模拟进度更新
			for(int i = 0; i<100;i++)
			{
				publishProgress(i);
				try{
					Thread.sleep(300);
				}catch(InterruptedException){
					e.printStackTrace();
				}
			}
			return null;
		}

		protected void onProgressUpdate(Integer... values){
			super.onProgressUpdate(values);
			//获取进度更新值
			mProgressBar.setProgress(values[0]);
		}
	}
}
//然后将此ProgressBarTest类部署至mainActivity中
但是这个会出现重复进入线程时,出现”bug“,只有将前面的AsyncTask完成后才能执行当前的任务,只需将AsyncTask生命周期与Activity生命周期一致即可,

只需要在onPause()方法中加入判断:

protected void onPause(){
	super.onPause();
	if(mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING){
		mTask.cancel(true);   
		//cancel()方法只是将对应的AsyncTask标记为cancel状态,并不是真的取消
		//故需要在doInBackground()和onProgressUpdate()方法中加入判断语句
	}
}
protected Void doInBackground(Void... params){
			//模拟进度更新
			for(int i = 0; i<100;i++)
			{
				if(isCancelled()){
					break;
				}
				publishProgress(i);
				try{
					Thread.sleep(300);
				}catch(InterruptedException){
					e.printStackTrace();
				}
			}
			return null;
		}

protected void onProgressUpdate(Integer... values){
	super.onProgressUpdate(values);
		if(isCancelled()){
			return;
		}
		//获取进度更新值
		mProgressBar.setProgress(values[0]);
	}

使用AsyncTask注意事项:

必须在UI线程中创建AsyncTask的实例

必须在UI线程中调用AsyncTask的execute()方法

重写的四个方法是系统自动调用的,不应手动调用

每个AsyncTask只能被执行一次,多次调用将会引发异常
只有doInBackground()方法是运行在其他线程,其他方法都是运行在主线程,即其他方法都可以更新UI,而只有这个方法需要做异步处理



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值