您的位置:首页 > 其它

AsyncTask(一)AsyncTask的使用

2016-11-03 18:58 141 查看
前言:虽然现在RxJava非常流行,但是还是觉得应该分析一下Android的原生异步线程实现。打算用2篇文章来过一下这个知识点。其中第一部分主要为使用例子,第二部分从源码的角度来验证那样使用的原因。第一篇:第二篇AsyncTask。顾名思义,异步的任务。android.os.AsyncTask是一个抽象类,其类定义如下:
publicabstractclassAsyncTask<Params,Progress,Result>
其中Params对应传入参数,Progress对应执行进度参数,Result对应执行结果参数。需要一一对应。doInBackground的参数和Params一致,返回结果和Result一致;onProgressUpdate的参数和Progress一致;onPostExecute的参数和Result一致。一个例子如下:
privateclassAsyncTaskDemoextendsAsyncTask<HashMap<String,String>,Integer,String>{
@Override
protectedStringdoInBackground(HashMap<String,String>...params){
returnnull;
}

@Override
protectedvoidonProgressUpdate(Integer...progress){

}

@Override
protectedvoidonPostExecute(Stringresult){
super.onPostExecute(result);
}
}
它有3个启动入口:
第一个用于串行执行;
第二个用于自定义执行,可以传入AsyncTask.THREAD_POOL_EXECUTOR进行并行计算;
第三用于执行制定Runnable。
它提供了5个生命周期方法:
其顺序为:
onPreExecute->doInBackGround->onPostExecute
publishProgress(需要手动调用,也就是说进度是自己计算的)->onProgressUpdate
onCacelled
其中,doInBackGround是个抽象方法,是AsyncTask实现类中必须要实现的。
此外,doInBackGround不在UIThread中执行,不能直接操作UI。
串行执行结果:
11-0315:47:11.28514236-14236/?D/thm:AsyncTask1:onPreExecute11-0315:47:11.28514236-14236/?D/thm:AsyncTask2:onPreExecute11-0315:47:11.28514236-14236/?D/thm:AsyncTask3:onPreExecute11-0315:47:11.28514236-14236/?D/thm:AsyncTask4:onPreExecute11-0315:47:11.31014236-14236/?D/thm:AsyncTask1:2011-0315:47:11.33514236-14236/?D/thm:AsyncTask1:4011-0315:47:11.36014236-14236/?D/thm:AsyncTask1:6011-0315:47:11.38514236-14236/?D/thm:AsyncTask1:8011-0315:47:11.41514236-14236/?D/thm:AsyncTask1:10011-0315:47:11.41514236-14236/?D/thm:AsyncTask1:isfinished11-0315:47:11.44514236-14236/?D/thm:AsyncTask2:2011-0315:47:11.47014236-14236/?D/thm:AsyncTask2:4011-0315:47:11.49514236-14236/?D/thm:AsyncTask2:6011-0315:47:11.52514236-14236/?D/thm:AsyncTask2:8011-0315:47:11.55014236-14236/?D/thm:AsyncTask2:10011-0315:47:11.55014236-14236/?D/thm:AsyncTask2:isfinished11-0315:47:11.57514236-14236/?D/thm:AsyncTask3:2011-0315:47:11.60514236-14236/?D/thm:AsyncTask3:4011-0315:47:11.63014236-14236/?D/thm:AsyncTask3:6011-0315:47:11.66014236-14236/?D/thm:AsyncTask3:8011-0315:47:11.68514236-14236/?D/thm:AsyncTask3:10011-0315:47:11.68514236-14236/?D/thm:AsyncTask3:isfinished11-0315:47:11.72014236-14236/?D/thm:AsyncTask4:2011-0315:47:11.74514236-14236/?D/thm:AsyncTask4:4011-0315:47:11.77014236-14236/?D/thm:AsyncTask4:6011-0315:47:11.80014236-14236/?D/thm:AsyncTask4:8011-0315:47:11.82514236-14236/?D/thm:AsyncTask4:10011-0315:47:11.82514236-14236/?D/thm:AsyncTask4:isfinished
并行执行结果:
11-0315:47:19.62014236-14236/?D/thm:AsyncTask1:onPreExecute11-0315:47:19.62514236-14236/?D/thm:AsyncTask2:onPreExecute11-0315:47:19.62514236-14236/?D/thm:AsyncTask3:onPreExecute11-0315:47:19.63514236-14236/?D/thm:AsyncTask4:onPreExecute11-0315:47:19.65514236-14236/?D/thm:AsyncTask2:2011-0315:47:19.65514236-14236/?D/thm:AsyncTask1:2011-0315:47:19.66014236-14236/?D/thm:AsyncTask3:2011-0315:47:19.68014236-14236/?D/thm:AsyncTask2:4011-0315:47:19.68014236-14236/?D/thm:AsyncTask1:4011-0315:47:19.68014236-14236/?D/thm:AsyncTask4:2011-0315:47:19.68514236-14236/?D/thm:AsyncTask3:4011-0315:47:19.70514236-14236/?D/thm:AsyncTask2:6011-0315:47:19.70514236-14236/?D/thm:AsyncTask1:6011-0315:47:19.71014236-14236/?D/thm:AsyncTask3:6011-0315:47:19.71514236-14236/?D/thm:AsyncTask4:4011-0315:47:19.73014236-14236/?D/thm:AsyncTask2:8011-0315:47:19.73514236-14236/?D/thm:AsyncTask1:8011-0315:47:19.73514236-14236/?D/thm:AsyncTask3:8011-0315:47:19.74014236-14236/?D/thm:AsyncTask4:6011-0315:47:19.75514236-14236/?D/thm:AsyncTask2:10011-0315:47:19.75514236-14236/?D/thm:AsyncTask2:isfinished11-0315:47:19.76014236-14236/?D/thm:AsyncTask1:10011-0315:47:19.76014236-14236/?D/thm:AsyncTask1:isfinished11-0315:47:19.76514236-14236/?D/thm:AsyncTask4:8011-0315:47:19.76514236-14236/?D/thm:AsyncTask3:10011-0315:47:19.76514236-14236/?D/thm:AsyncTask3:isfinished11-0315:47:19.79014236-14236/?D/thm:AsyncTask4:10011-0315:47:19.79014236-14236/?D/thm:AsyncTask4:isfinished
看时间,显然并行执行消耗的总时间远低于串行执行。
但并行执行有其不安全性,即之前的数据可能会覆盖后面的数据。
比如以下MyAsyncTask2,同时启动4个Task:
staticinti=0;privateclassMyAsyncTask2extendsAsyncTask<Void,Integer,Void>{privateStringmName="AsyncTask";publicMyAsyncTask2(intid){super();mName+=id;}@OverrideprotectedvoidonPreExecute(){Log.d("thm",mName+":onPreExecute");}@OverrideprotectedVoiddoInBackground(Void...voids){for(;i<100;){try{Thread.sleep(25);}catch(Exceptione){e.printStackTrace();}//Log.d("thm",mName+":"+i);publishProgress(++i);}returnnull;}@OverrideprotectedvoidonProgressUpdate(Integer...progress){Log.d("thm",mName+":"+progress[0]);}@OverrideprotectedvoidonPostExecute(VoidaVoid){super.onPostExecute(aVoid);Log.d("thm",mName+":"+"isfinished");}}
运行结果如下,显然,这里执行了103次,而我们的预期目标是100次:
11-0316:21:09.49931561-31561/?D/thm:AsyncTask1:onPreExecute11-0316:21:09.50431561-31561/?D/thm:AsyncTask2:onPreExecute11-0316:21:09.50931561-31561/?D/thm:AsyncTask3:onPreExecute11-0316:21:09.50931561-31561/?D/thm:AsyncTask4:onPreExecute11-0316:21:09.53431561-31561/?D/thm:AsyncTask1:111-0316:21:09.53431561-31561/?D/thm:AsyncTask2:211-0316:21:09.53431561-31561/?D/thm:AsyncTask3:311-0316:21:09.53431561-31561/?D/thm:AsyncTask4:411-0316:21:09.55931561-31561/?D/thm:AsyncTask2:511-0316:21:09.55931561-31561/?D/thm:AsyncTask1:611-0316:21:09.55931561-31561/?D/thm:AsyncTask3:711-0316:21:09.56431561-31561/?D/thm:AsyncTask4:811-0316:21:09.58431561-31561/?D/thm:AsyncTask1:1011-0316:21:09.58431561-31561/?D/thm:AsyncTask3:1111-0316:21:09.58431561-31561/?D/thm:AsyncTask2:911-0316:21:09.58931561-31561/?D/thm:AsyncTask4:1211-0316:21:09.60931561-31561/?D/thm:AsyncTask1:1311-0316:21:09.60931561-31561/?D/thm:AsyncTask3:1411-0316:21:09.60931561-31561/?D/thm:AsyncTask2:1511-0316:21:09.61431561-31561/?D/thm:AsyncTask4:1611-0316:21:09.63431561-31561/?D/thm:AsyncTask1:1711-0316:21:09.63431561-31561/?D/thm:AsyncTask3:1811-0316:21:09.63431561-31561/?D/thm:AsyncTask2:1911-0316:21:09.63931561-31561/?D/thm:AsyncTask4:2011-0316:21:09.65931561-31561/?D/thm:AsyncTask1:2111-0316:21:09.65931561-31561/?D/thm:AsyncTask3:2211-0316:21:09.65931561-31561/?D/thm:AsyncTask2:2311-0316:21:09.66431561-31561/?D/thm:AsyncTask4:2411-0316:21:09.68431561-31561/?D/thm:AsyncTask1:2511-0316:21:09.68431561-31561/?D/thm:AsyncTask3:2611-0316:21:09.68431561-31561/?D/thm:AsyncTask2:2711-0316:21:09.68931561-31561/?D/thm:AsyncTask4:2811-0316:21:09.70931561-31561/?D/thm:AsyncTask3:3011-0316:21:09.70931561-31561/?D/thm:AsyncTask1:2911-0316:21:09.70931561-31561/?D/thm:AsyncTask2:3111-0316:21:09.71431561-31561/?D/thm:AsyncTask4:3211-0316:21:09.73431561-31561/?D/thm:AsyncTask1:3311-0316:21:09.73431561-31561/?D/thm:AsyncTask3:3511-0316:21:09.73431561-31561/?D/thm:AsyncTask2:3411-0316:21:09.73931561-31561/?D/thm:AsyncTask4:3611-0316:21:09.75931561-31561/?D/thm:AsyncTask1:3711-0316:21:09.75931561-31561/?D/thm:AsyncTask3:3811-0316:21:09.76431561-31561/?D/thm:AsyncTask2:3911-0316:21:09.76431561-31561/?D/thm:AsyncTask4:4011-0316:21:09.78931561-31561/?D/thm:AsyncTask3:4111-0316:21:09.78931561-31561/?D/thm:AsyncTask1:4211-0316:21:09.78931561-31561/?D/thm:AsyncTask4:4411-0316:21:09.79431561-31561/?D/thm:AsyncTask2:4311-0316:21:09.81431561-31561/?D/thm:AsyncTask3:4511-0316:21:09.81431561-31561/?D/thm:AsyncTask1:4611-0316:21:09.81431561-31561/?D/thm:AsyncTask4:4711-0316:21:09.81931561-31561/?D/thm:AsyncTask2:4811-0316:21:09.83931561-31561/?D/thm:AsyncTask1:4911-0316:21:09.83931561-31561/?D/thm:AsyncTask3:5011-0316:21:09.84431561-31561/?D/thm:AsyncTask2:5211-0316:21:09.84431561-31561/?D/thm:AsyncTask4:5111-0316:21:09.86431561-31561/?D/thm:AsyncTask1:5311-0316:21:09.86431561-31561/?D/thm:AsyncTask3:5411-0316:21:09.86931561-31561/?D/thm:AsyncTask2:5511-0316:21:09.86931561-31561/?D/thm:AsyncTask4:5611-0316:21:09.89431561-31561/?D/thm:AsyncTask1:5711-0316:21:09.89431561-31561/?D/thm:AsyncTask2:5811-0316:21:09.89931561-31561/?D/thm:AsyncTask3:5911-0316:21:09.89931561-31561/?D/thm:AsyncTask4:6011-0316:21:09.92431561-31561/?D/thm:AsyncTask1:6111-0316:21:09.92431561-31561/?D/thm:AsyncTask2:6211-0316:21:09.92431561-31561/?D/thm:AsyncTask3:6411-0316:21:09.92431561-31561/?D/thm:AsyncTask4:6311-0316:21:09.94931561-31561/?D/thm:AsyncTask1:6511-0316:21:09.94931561-31561/?D/thm:AsyncTask2:6611-0316:21:09.94931561-31561/?D/thm:AsyncTask3:6711-0316:21:09.94931561-31561/?D/thm:AsyncTask4:6811-0316:21:09.97431561-31561/?D/thm:AsyncTask1:6911-0316:21:09.97431561-31561/?D/thm:AsyncTask3:7011-0316:21:09.97431561-31561/?D/thm:AsyncTask4:7011-0316:21:09.97931561-31561/?D/thm:AsyncTask2:7111-0316:21:09.99931561-31561/?D/thm:AsyncTask1:7211-0316:21:10.00431561-31561/?D/thm:AsyncTask4:7411-0316:21:10.00431561-31561/?D/thm:AsyncTask3:7311-0316:21:10.00931561-31561/?D/thm:AsyncTask2:7511-0316:21:10.02431561-31561/?D/thm:AsyncTask1:7611-0316:21:10.02931561-31561/?D/thm:AsyncTask4:7711-0316:21:10.03931561-31561/?D/thm:AsyncTask3:7911-0316:21:10.04431561-31561/?D/thm:AsyncTask2:7811-0316:21:10.04931561-31561/?D/thm:AsyncTask1:8011-0316:21:10.05431561-31561/?D/thm:AsyncTask4:8111-0316:21:10.06431561-31561/?D/thm:AsyncTask3:8211-0316:21:10.06931561-31561/?D/thm:AsyncTask2:8311-0316:21:10.07931561-31561/?D/thm:AsyncTask1:8411-0316:21:10.07931561-31561/?D/thm:AsyncTask4:8511-0316:21:10.09431561-31561/?D/thm:AsyncTask3:8611-0316:21:10.10431561-31561/?D/thm:AsyncTask2:8711-0316:21:10.11431561-31561/?D/thm:AsyncTask4:8811-0316:21:10.11431561-31561/?D/thm:AsyncTask1:8911-0316:21:10.11931561-31561/?D/thm:AsyncTask3:9011-0316:21:10.12931561-31561/?D/thm:AsyncTask2:9111-0316:21:10.13931561-31561/?D/thm:AsyncTask4:9211-0316:21:10.13931561-31561/?D/thm:AsyncTask1:9311-0316:21:10.14431561-31561/?D/thm:AsyncTask3:9411-0316:21:10.15431561-31561/?D/thm:AsyncTask2:9511-0316:21:10.16931561-31561/?D/thm:AsyncTask3:9711-0316:21:10.16931561-31561/?D/thm:AsyncTask4:9611-0316:21:10.16931561-31561/?D/thm:AsyncTask1:9811-0316:21:10.17931561-31561/?D/thm:AsyncTask2:9911-0316:21:10.21931561-31561/?D/thm:AsyncTask2:10011-0316:21:10.21931561-31561/?D/thm:AsyncTask2:isfinished11-0316:21:10.21931561-31561/?D/thm:AsyncTask1:10111-0316:21:10.21931561-31561/?D/thm:AsyncTask1:isfinished11-0316:21:10.21931561-31561/?D/thm:AsyncTask4:10211-0316:21:10.21931561-31561/?D/thm:AsyncTask4:isfinished11-0316:21:10.21931561-31561/?D/thm:AsyncTask3:10311-0316:21:10.21931561-31561/?D/thm:AsyncTask3:isfinished
两种execute方式各有所长,具体使用那种还需依据实际情况来做。
当然现在的主流已经不再是AsyncTask了,比如现在很火爆的异步框架RxJava,采用观察者+异步的方式,且书写起来十分简便。
除去上面所提到的安全性,使用AsyncTask还需注意下面这些:
1.生命周期
AsyncTask不会随着Activity的销毁而销毁,它会一直执行直到doInBackground()方法执行完毕,然后执行onPostExecute/onCancelled。
如果我们的Activity销毁之前,没有取消AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。
因为它想要处理的view已经不在了。所以,我们总是必须确保在销毁活动之前取消任务。
2.内存泄漏
如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对Activity的引用。
如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄漏。
3.结果丢失
屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,
这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。
总之,如果在onPostExecute()中执行UI操作的话,必须在Activity的onDestroy()中做处理。4.AsyncTask的类必须在UI线程加载(从4.1开始系统会帮我们自动完成),AsyncTask对象必须在UI线程创建5.execute方法必须在UI线程调用6.不要在你的程序中去直接调用onPreExecute(),onPostExecute,doInBackground,onProgressUpdate方法7.一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常8.AsyncTask不是被设计为处理耗时操作的,耗时上限为几秒钟,如果要做长耗时操作,强烈建议你使用Executor,ThreadPoolExecutor以及FutureTask官方文档如下:TheAsyncTaskclassmustbeloadedontheUIthread.Thisisdoneautomaticallyasof 
JELLY_BEAN
.ThetaskinstancemustbecreatedontheUIthread.
execute(Params...)
 mustbeinvokedontheUIthread.Donotcall 
onPreExecute()
onPostExecute(Result)
doInBackground(Params...)
onProgressUpdate(Progress...)
 manually.Thetaskcanbeexecutedonlyonce(anexceptionwillbethrownifasecondexecutionisattempted.)测试代码比较少,这里直接附上:
packagetian.hangmin.com.asyntaskdemo;importandroid.app.Activity;importandroid.content.Context;importandroid.os.AsyncTask;importandroid.os.Bundle;importandroid.util.Log;importandroid.view.View;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.Map;/***Createdbytianhmon2016/11/3.*/publicclassAsynTaskActivityextendsActivity{@OverrideprotectedvoidonCreate(BundleonSavedInstanceState){super.onCreate(onSavedInstanceState);setContentView(R.layout.activity_asyntask_demo);findViewById(R.id.button1).setOnClickListener(listener);findViewById(R.id.button2).setOnClickListener(listener);}View.OnClickListenerlistener=newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){start(v.getId());}};protectedvoidstart(intid){if(id==R.id.button1){newMyAsyncTask(1).execute();newMyAsyncTask(2).execute();newMyAsyncTask(3).execute();newMyAsyncTask(4).execute();}elseif(id==R.id.button2){newMyAsyncTask(1).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);newMyAsyncTask(2).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);newMyAsyncTask(3).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);newMyAsyncTask(4)cf0e.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);}elseif(i==R.id.button3){newMyAsyncTask2(1).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);newMyAsyncTask2(2).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);newMyAsyncTask2(3).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);newMyAsyncTask2(4).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,newVoid[1]);}}privateclassMyAsyncTaskextendsAsyncTask<Void,Integer,Void>{privateStringmName="AsyncTask";publicMyAsyncTask(intid){super();mName+=id;}@OverrideprotectedvoidonPreExecute(){Log.d("thm",mName+":onPreExecute");}@OverrideprotectedVoiddoInBackground(Void...voids){for(inti=0;i<100;){try{Thread.sleep(25);}catch(Exceptione){e.printStackTrace();}//Log.d("thm",mName+":"+i);publishProgress(++i*100/5);}returnnull;}@OverrideprotectedvoidonProgressUpdate(Integer...progress){Log.d("thm",mName+":"+progress[0]);}@OverrideprotectedvoidonPostExecute(VoidaVoid){super.onPostExecute(aVoid);Log.d("thm",mName+":"+"isfinished");}}staticinti=0;privateclassMyAsyncTask2extendsAsyncTask<Void,Integer,Void>{privateStringmName="AsyncTask";publicMyAsyncTask2(intid){super();mName+=id;}@OverrideprotectedvoidonPreExecute(){Log.d("thm",mName+":onPreExecute");}@OverrideprotectedVoiddoInBackground(Void...voids){for(;i<100;){try{Thread.sleep(25);}catch(Exceptione){e.printStackTrace();}//Log.d("thm",mName+":"+i);publishProgress(++i);}returnnull;}@OverrideprotectedvoidonProgressUpdate(Integer...progress){Log.d("thm",mName+":"+progress[0]);}@OverrideprotectedvoidonPostExecute(VoidaVoid){super.onPostExecute(aVoid);Log.d("thm",mName+":"+"isfinished");}}}
xml
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/button1"android:layout_marginTop="8dp"android:text="串行开始"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/button2"android:layout_marginTop="8dp"android:text="并行开始"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/button3"android:layout_marginTop="8dp"android:text="并行不安全"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AsyncTask Anroid 异步