AsyncTask详解
1. 什么是AsyncTask?
封装了线程池和Handler,这个框架主要是用来执行异步任务的,内部集成了Handler,所以它可以很灵活的在UI线程和异步线程之间进行切换。
2. AsyncTask介绍
-
三个参数
AsyncTask
3. AsyncTask实例
-
创建AsyncTask的子类,实现各方法,分别处理相应的逻辑。
public class MyAsyncTask extends AsyncTask<Integer,Integer,String> {
private static final String TAG = MyAsyncTask.class.getSimpleName();
private final TextView tv;
public MyAsyncTask(TextView tv) {
this.tv = tv;
}
@Override
protected void onPreExecute() {
Log.d(TAG,"任务开始执行");
super.onPreExecute();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
tv.append("\n"+s);
Log.d(TAG,"任务结果:"+s);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (tv!=null){
tv.setText("当前进度是:"+values[0]+"%");
}
}
@Override
protected String doInBackground(Integer... params) {
for (int i=0;i<=100;i+=10){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//将进度通知发送到主线程
publishProgress(i);
}
return "执行完成";
}
} -
在Activity中调用执行
public class AsyncTaskActivity extends Activity implements View.OnClickListener {
private Button bt;
private TextView tv;
private MyAsyncTask myAsyncTask;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
tv = (TextView) findViewById(R.id.tv);
bt.setOnClickListener(this);
myAsyncTask = new MyAsyncTask(tv);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.bt){
myAsyncTask.execute(0);
}
}
} -
动态图执行结果
02-03 14:04:16.289 8379-8379/async.com.androidasync D/MyAsyncTask: 任务开始执行
02-03 14:04:27.354 8379-8379/async.com.androidasync D/MyAsyncTask: 任务结果:执行完成
02-03 14:18:01.361 8379-8379/async.com.androidasync D/ActivityThreadInjector: clearCachedDrawables.
02-03 14:18:09.510 8379-8379/async.com.androidasync D/MyAsyncTask: 任务开始执行
02-03 14:18:20.539 8379-8379/async.com.androidasync D/MyAsyncTask: 任务结果:执行完成
4. AsyncTask机制原理
- AsyncTask的本质是一个静态的线程池,派生出的子类可以执行不同的异步任务,异步任务都提交到静态线程池中执行。
- 线程池中的异步线程是执行doInBackground来完成的
- 当任务状态改变的时候,异步线程会向UI线程发送消息,AsyncTask内部的Handler会及时的调用相关方法更新UI。
5. AsyncTask存在的缺陷
- 内存泄漏,同Handler一样,非静态内部类持有外部类的引用导致内存泄漏
- AsyncTask的生命周期和Activity是不一致的,需要在Activity的onDestory方法中调用AsyncTask的cancle方法,取消任务执行。否则可能会导致崩溃。
- 结果丢失:同第二条;在屏幕旋转或者activity在内存不够时,被系统杀掉,此时AsyncTask持有的Activity已经失效,调用更新UI的方法则会失效。
- 并行或串行(可以调用executeOnExecutor来执行并行任务):建议只用串行,避免多线程运行影响线程池的稳定性 。