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来执行并行任务):建议只用串行,避免多线程运行影响线程池的稳定性 。