Android AsyncTask

一、异步任务加载网络数据:

Android中提供了一个异步任务的类AsyncTask,简单来说,这个类中的任务是运行在后台线程中的,并可以将结果放到UI线程中进行处理,它定义了三种泛型,分别是ParamsProgressResult,分别表示请求的参数、任务的进度和获得的结果数据。

1、使用原因:

1)是其中使用了线程池技术,而且其中的方法很容易实现调用

2)可以调用相关的方法,在开启子线程前和后,进行界面的更新

3)一旦任务多了,不用每次都new新的线程,可以直接使用

2、执行的顺序:

onPreExecute()【执行前开启】--- > doInBackground() --- >onProgressUpdate() --- > onPostExecute()

3、执行过程:

当一个异步任务开启后,执行过程如下:

1)、onPreExecute()

这个方法是执行在主线程中的。这步操作是用于准备好任务的,作为任务加载的准备工作。建议在这个方法中弹出一个提示框。

2)、doInBackground()

这个方法是执行在子线程中的。在onPreExecute()执行完后,会立即开启这个方法,在方法中可以执行耗时的操作。需要将请求的参数传递进来,发送给服务器,并将获取到的数据返回,数据会传给最后一步中;这些值都将被放到主线程中,也可以不断的传递给下一步的onProgressUpdate()中进行更新。可以通过不断调用publishProgress(),将数据(或进度)不断传递给onProgressUpdate()方法,进行不断更新界面。

3)、onProgressUpdate()

这个方法是执行在主线程中的。publishProgress()doInBackground()中被调用后,才开启的这个方法,它在何时被开启是不确定的,执行这个方法的过程中,doInBackground()是仍在执行的,即子线程还在运行着。

4)、onPostExecute()

这个方法是执行在主线程中的。当后台的子线程执行完毕后才调用此方法。doInBackground()返回的结果会作为参数被传递过来。可以在这个方法中进行更新界面的操作。

5)、execute()

最后创建AsyncTask自定义的类,开启异步任务。

 

3、实现原理:

1)、线程池的创建:

3.0之前,在创建了AsyncTask的时候,会默认创建一个线程池ThreadPoolExecutor,并默认创建出5个线程放入到线程池中,最多可防128个线程当我们尝试去添加第129个任务时,程序就会崩溃;且这个线程池是公共的唯一一份。3.0之后,SerialExecutor也是AsyncTask在3.0版本以后做了最主要的修改的地方,它在AsyncTask中是以常量的形式被使用的,因此在整个应用程序中的所有AsyncTask实例都会共用同一个SerialExecutor,SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态。Android照片墙应用实现,再多的图片也不怕崩溃。

2)、任务的执行:

execute中,会执行run方法,当执行完run方法后,会调用scheduleNext()不断的从双端队列中轮询,获取下一个任务并继续放到一个子线程中执行,直到异步任务执行完毕。

3)、消息的处理:

在执行完onPreExecute()方法之后,执行了doInBackground()方法,然后就不断的发送请求获取数据;在这个AsyncTask中维护了一个InternalHandler的类,这个类是继承Handler的,获取的数据是通过handler进行处理和发送的。在其handleMessage方法中,将消息传递给onProgressUpdate()进行进度的更新,也就可以将结果发送到主线程中,进行界面的更新了。

 

4、需要注意的是:

①、这个AsyncTask类必须由子类调用

②、虽然是放在子线程中执行的操作,但是不建议做特别耗时的操作,如果操作过于耗时,建议使用线程池ThreadPoolExecutor和FutureTask


5、如果不想使用默认的线程池,还可以自由地进行配置。比如使用如下的代码来启动任务:

Executor exec = new ThreadPoolExecutor(15, 200, 10,
		TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
new DownloadTask().executeOnExecutor(exec);
这样就可以使用我们自定义的一个Executor来执行任务,而不是使用SerialExecutor。上述代码的效果允许


在同一时刻有15个任务正在执行,并且最多能够存储200个任务。

package com.example.asynctask;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URLConnection;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity implements OnClickListener{
	
	private ImageView image;
	private ProgressDialog progress;
	private Button btn_download;
	private static String URL="http://";//图片链接
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		image=(ImageView) findViewById(R.id.iv_image);
		btn_download=(Button) findViewById(R.id.btn_download);
		progress=new ProgressDialog(this);
		progress.setIcon(R.drawable.ic_launcher);
		progress.setTitle("提示信息");
		progress.setMessage("正在下载,请稍候...");
		progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		btn_download.setOnClickListener(this);
	}
	
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		new MyAsyncTask().execute(URL);
	}
	/*
	 * String*********对应我们的URL类型
	 * Integer********进度条的进度值
	 * BitMap*********异步任务完成后返回的类型  
	 * */
	class MyAsyncTask extends AsyncTask<String, Integer, Bitmap>{
		
		//执行异步任务(doInBackground)之前执行,并且在ui线程中执行
		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
			if(image!=null){
				image.setVisibility(View.GONE);
			}
			//开始下载 对话框进度条显示
			progress.show();
			progress.setProgress(0);
		}
		
		@Override
		protected Bitmap doInBackground(String... params) {
			// TODO Auto-generated method stub
			//params是一个可变长的数组 在这里我们只传进来了一个url 
			String url=params[0];
			Bitmap bitmap=null;
			URLConnection connection;
			InputStream is;//用于获取数据的输入流
			ByteArrayOutputStream bos;//可以捕获内存缓冲区的数据,转换成字节数组。
			int len;
			float count=0,total;//count为图片已经下载的大小 total为总大小
			try {
				//获取网络连接对象
				connection=(URLConnection) new java.net.URL(url).openConnection();
				//获取当前页面的总长度
				total=(int)connection.getContentLength();
				//获取输入流
				is=connection.getInputStream();
				bos=new ByteArrayOutputStream();
				byte []data=new byte[1024];
				while((len=is.read(data))!=-1){
					count+=len;
					bos.write(data,0,len);
					//调用publishProgress公布进度,最后onProgressUpdate方法将被执行
					publishProgress((int)(count/total*100));
					//为了显示出进度 人为休眠0.5秒
					Thread.sleep(500);
				}
				bitmap=BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.toByteArray().length);
				is.close();
				bos.close();
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return bitmap;
		}
		//在ui线程中执行 可以操作ui
		@Override
		protected void onPostExecute(Bitmap bitmap) {
			// TODO Auto-generated method stub
			super.onPostExecute(bitmap);
			//下载完成 对话框进度条隐藏
			progress.cancel();
			image.setImageBitmap(bitmap);
			image.setVisibility(View.VISIBLE);
		}
		
		/*
		 * 在doInBackground方法中已经调用publishProgress方法 更新任务的执行进度后
		 * 调用这个方法 实现进度条的更新
		 * */
		@Override
		protected void onProgressUpdate(Integer... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
			progress.setProgress(values[0]);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值