AsyncTask是Android为了简化异步操作而封装的异步任务操作抽象类。当我们需要在程序中执行耗时的异步操作时,我们可以考虑使用AsyncTask来实现。
那么Android中为什么需要异步任务操作呢?
★Android是单线程模型
★Android中UI主线程不能进行耗时操作,否则可能报ANR异常。
使用AsyncTask比较简单,因为它是抽象类,我们通常会写一个类来继承AsyncTask<Params,Progress,Result>,继承AsyncTask需要指定三个泛型参数,参数分别表示为:
★Params:启动任务时输入的参数类型,比如我们输入的String类型url
★Progress:后台任务执行中返回的进度值类型,通常来更新ui进度
★Result:耗时操作完成后返回的结果。
同时实现AsyncTask类还需要重写相应的回调方法,一般我们用到的有如下四个方法:
★doInBackground(Void... params):必须重写,异步执行耗时操作
★onPreExecute():执行耗时操作前被调用,通常用来完成一些初始化操作
★onProgressUpdate(Void... values):将doInBackground方法返回的值传递给该方法,在doInBackground中调用publishProgroess()方法可以且来更新进度
★onPostExecute(Void result):耗时的异步任务完成后回调该方法
下面开始学习内容:
首先我们看下AsyncTask执行耗时操作时对应方法的执行顺序):
这样我们可以很明显看出相应方法的执行顺序。
接下来我们看加载图片,还是截图:
第三个小点模拟进度显示就是在Actitivty上显示一个不断加载的进度条,就不贴图啦。
下面是上面三个小点的代码----->主界面代码(对应布局就是三个Button)
public class MainActivity extends Activity implements OnClickListener {
private Button circleBtn, picBtn, progressBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intViews();
initListeners();
}
private void intViews() {
this.circleBtn = (Button) findViewById(R.id.circle_btn);
this.picBtn = (Button) findViewById(R.id.load_pic_btn);
this.progressBtn = (Button) findViewById(R.id.progress_btn);
}
private void initListeners() {
this.circleBtn.setOnClickListener(this);
this.picBtn.setOnClickListener(this);
this.progressBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.circle_btn:
startActivity(new Intent(MainActivity.this, LifeCircleActivity.class));
break;
case R.id.load_pic_btn:
startActivity(new Intent(MainActivity.this, LoadImageActivity.class));
break;
case R.id.progress_btn:
startActivity(new Intent(MainActivity.this, ProgressActivity.class));
break;
}
}
}
---------->查看AsyncTask执行方法顺序代码(对应布局空页面:
public class LifeCircleActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_kongbai);
new CircleAsynctask().execute();
}
class CircleAsynctask extends AsyncTask<Void, Void, Void> {
/* 实现AsyncTask必须实现的方法:异步执行后台线程将要完成耗时操作* */
@Override
protected Void doInBackground(Void... params) {
publishProgress();
Log.e("ldm", "doInBackground");
return null;
}
/* 实现AsyncTask必须实现的方法:异步执行后台线程将要完成耗时操作* */
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.e("ldm", "onPostExecute");
}
/* 执行后台耗时操作前被调用,通常用户完成一些初始化操作* */
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.e("ldm", "onPreExecute");
}
/* 将doInBackground方法返回的值传递到该方法,并可以更新主线程ui* */
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
Log.e("ldm", "onProgressUpdate");
}
}
---------->异步加载网络图片代码(对应布局就是Button+ImageView):
public class LoadImageActivity extends Activity {
private ImageView mImageView;
private ProgressBar mProgressBar;
private Button mButton;
private static final String IMAGE_URL = "http://pic.qiantucdn.com/58pic/16/85/34/72K58PICjMU_1024.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_image);
intViewsAndEvents();
}
private void intViewsAndEvents() {
this.mImageView = (ImageView) findViewById(R.id.load_image);
this.mProgressBar = (ProgressBar) findViewById(R.id.load_bar);
this.mButton = (Button) findViewById(R.id.load_pic_btn);
this.mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new LoadImageAsynctask().execute(IMAGE_URL);
}
});
}
class LoadImageAsynctask extends AsyncTask<String, Void, Bitmap> {
/* 实现AsyncTask必须实现的方法:异步执行后台线程将要完成耗时操作* */
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];// 获取传递进来的参数
Bitmap bitmap = null;
URLConnection conn = null;
InputStream in;
try {
conn = new URL(url).openConnection();
in = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(in);
// 通过BitmapFactory.decodeStream()方法解析输入流
bitmap = BitmapFactory.decodeStream(bis);
in.close();
bis.close();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmap;// 返回Bitmap
}
/* 实现AsyncTask必须实现的方法:异步执行后台线程将要完成耗时操作* */
@Override
protected void onPostExecute(Bitmap result) {
mProgressBar.setVisibility(View.GONE);
mImageView.setImageBitmap(result);// 加载完成显示图片
}
/* 执行后台耗时操作前被调用,通常用户完成一些初始化操作* */
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);// 后台执行前显示加载框
}
/* 将doInBackground方法返回的值传递到该方法,并可以更新主线程ui* */
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
}
--------->模拟进度条进度代码(对应布局仅仅一个ProgressBar):
public class ProgressActivity extends Activity {
private ProgressBar mProgressBar;
private ProgressAsynctask mAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress);
this.mProgressBar = (ProgressBar) findViewById(R.id.mpbar);
mAsyncTask = new ProgressAsynctask();
mAsyncTask.execute();
}
@Override
protected void onPause() {
super.onPause();
if (mAsyncTask != null && mAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {// 判断当前异步任务是否在进行中
// cancel()方法只是将对应的AsyncTask状态标记为cancel状态,并没有真正取消异步操作
mAsyncTask.cancel(true);
}
}
class ProgressAsynctask extends AsyncTask<Void, Integer, Void> {
/* 实现AsyncTask必须实现的方法:异步执行后台线程将要完成耗时操作* */
@Override
protected Void doInBackground(Void... params) {
for (int i = 0; i < 100; i++) {
if (isCancelled()) {// 如果异步任务取消,则跳出循环
break;
}
publishProgress(i);
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
/* 实现AsyncTask必须实现的方法:异步执行后台线程将要完成耗时操作* */
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
/* 执行后台耗时操作前被调用,通常用户完成一些初始化操作* */
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/* 将doInBackground方法返回的值传递到该方法,并可以更新主线程ui* */
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (isCancelled()) {// 如果异步任务取消,则跳出循环
return;
}
mProgressBar.setProgress(values[0]);// 进度条数值显示
}
}
}
最后总结下使用AsyncTask执行异步操作注意事项:
★ AsyncTask的实例(子类)必须在UI主线程中创建
★ AsyncTask的execute()方法也必须在UI主线程中调用
★重写的四个方法是系统自动调用,不能手动更改
★每个AsyncTask只能被同时执行一次,多次调用将导致异常