Android 70 AsyncTask分析Word下载.docx

上传人:b****6 文档编号:17897482 上传时间:2022-12-12 格式:DOCX 页数:16 大小:22.69KB
下载 相关 举报
Android 70 AsyncTask分析Word下载.docx_第1页
第1页 / 共16页
Android 70 AsyncTask分析Word下载.docx_第2页
第2页 / 共16页
Android 70 AsyncTask分析Word下载.docx_第3页
第3页 / 共16页
Android 70 AsyncTask分析Word下载.docx_第4页
第4页 / 共16页
Android 70 AsyncTask分析Word下载.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

Android 70 AsyncTask分析Word下载.docx

《Android 70 AsyncTask分析Word下载.docx》由会员分享,可在线阅读,更多相关《Android 70 AsyncTask分析Word下载.docx(16页珍藏版)》请在冰豆网上搜索。

Android 70 AsyncTask分析Word下载.docx

AsyncTask执行时的输入参数的类型;

Progress:

后台执行任务时,计算出的完成进度的数值类型;

Result:

AsyncTask执行完毕后的返回类型。

这些模板参数并不一定需要全部定义,对于不用的参数,指定其为Void即可,例如:

privateclassMyTaskextendsAsyncTask<

Void,Void,Void>

{...}

1

Whenanasynchronoustaskisexecuted,thetaskgoesthrough4steps:

AsyncTask定义了4个回调接口,分别为onPreExecute、doInBackground、onProgressUpdate和onPostExecute。

onPreExecute,invokedontheUIthreadbeforethetaskisexecuted.

Thisstepisnormallyusedtosetupthetask,forinstancebyshowingaprogressbarintheuserinterface.

UI线程启动AsyncTask前,会先调用AsyncTask的onPreExecute。

这个接口中的操作主要用于做一些准备工作,例如创建任务对应的进度条。

doInBackground,invokedonthebackgroundthreadimmediatelyafteronPreExecute()finishesexecuting.

Thisstepisusedtoperformbackgroundcomputationthatcantakealongtime.

Theparametersoftheasynchronoustaskarepassedtothisstep.

Theresultofthecomputationmustbereturnedbythisstepandwillbepassedbacktothelaststep.

Thisstepcanalsouse{publishProgresstopublishoneormoreunitsofprogress.

ThesevaluesarepublishedontheUIthread,intheProgressUpdatestep.

当UI线程执行完onPreExecute函数后,后台线程将立即调用doInBackground接口。

doInBackground接口负责完成主要的耗时工作,AsyncTask执行时的输入参数将传递到doInBackground接口。

doInBackground中完成耗时工作后,必须返回执行结果(与模板参数Result一致)。

在doInBackground中可以调用publishProgress接口更新进度条,

进度条的数值将通过onProgressUpdate接口更新到UI界面。

onProgressUpdate,invokedontheUIthreadafteracalltopublishProgress.Thetimingoftheexecutionisundefined.

Thismethodisusedtodisplayanyformofprogressintheuserinterfacewhilethebackgroundcomputationisstillexecuting.

Forinstance,itcanbeusedtoanimateaprogressbarorshowlogsinatextfield.

当后台线程调用了publishProgress接口后,UI线程将在合适的时间内调用onProgressUpdate函数(由系统决定调用时间)。

在onProgressUpdate函数中,UI线程可以更新进度条信息。

onPostExecute,invokedontheUIthreadafterthebackgroundcomputationfinishes.

Theresultofthebackgroundcomputationispassedtothisstepasaparameter.

后台线程完成工作后,UI线程将调用onPostExecute接口,doInBackground的返回结果将作为该函数的输入参数。

AsyncTaskmustbesubclassedtobeused.ThesubclasswilloverrideatleastonemethoddoInBackground,

andmostoftenwilloverrideasecondoneonPostExecute.

在使用AsyncTask时,通常定义继承该类的子类,并覆盖其中的doInBackground、onPostExecute等函数。

Ataskcanbecancelledatanytimebyinvokingcancel(boolean).

InvokingthismethodwillcausesubsequentcallstoisCancelled()toreturntrue.

Afterinvokingthismethod,onCancelled(Object),insteadof

onPostExecute(Object)willbeinvokedafterdoInBackground(Object[])returns.

Toensurethatataskiscancelledasquicklyaspossible,youshouldalwayscheckthereturnvalueofisCancelled()

periodicallyfromdoInBackground(Object[]),ifpossible(insidealoopforinstance.)

调用AsyncTask的cancel接口可以结束任务。

当调用了cancel接口后,doInBackground结束后,将回调onCancelled接口而不是onPostExecute接口。

为了尽可能快的相应结束命令,应该在doInBackground函数中周期性的检测isCancelled接口的返回值。

Thereareafewthreadingrulesthatmustbefollowedforthisclasstoworkproperly:

1.TheAsyncTaskclassmustbeloadedontheUIthread.

2.ThetaskinstancemustbecreatedontheUIthread.

3.executemustbeinvokedontheUIthread.

4.DonotcallonPreExecute(),onPostExecute,doInBackground,

onProgressUpdatemanually.

5.Thetaskcanbeexecutedonlyonce(anexceptionwillbethrownifasecondexecutionisattempted.)

AsyncTask的加载、创建和启动必须在UI线程完成。

不要手动调用AsyncTask的onPreExecute、onPostExecute、doInBackground和onProgressUpdate接口。

每个AsyncTask只能执行一次,重复执行将会抛出异常。

AsyncTaskguaranteesthatallcallbackcallsaresynchronizedinsuchawaythatthefollowing

operationsaresafewithoutexplicitsynchronizations.

1.SetmemberfieldsintheconstructororonPreExecute,andrefertothem

indoInBackground.

2.SetmemberfieldsindoInBackground,andrefertothemin

onProgressUpdateandonPostExecute.

为了保证线程安全,doInBackground中引用的AsyncTask成员变量,必须事先初始化于构造函数或onPreExecute。

doInBackground中初始化的成员变量,由onProgressUpdate和onPostExecute使用。

Whenfirstintroduced,AsyncTaskswereexecutedseriallyonasinglebackgroundthread.

Startingwithandroid.os.Build.VERSION_CODES.DONUT,thiswaschangedtoapoolofthreadsallowingmultipletaskstooperateinparallel.

Startingwithandroid.os.Build.VERSION_CODES.HONEYCOMB,tasksareexecutedonasinglethread

toavoidcommonapplicationerrorscausedbyparallelexecution.

Ifyoutrulywantparallelexecution,youcaninvokeexecuteOnExecutor(java.util.concurrent.Executor,Object[])withTHREAD_POOL_EXECUTOR.

从文档来看,AsyncTask默认将在单一的后台线程中执行,

如果需要并发执行,则可以使用AsyncTask的executeOnExecutor接口。

了解AsyncTask的基本定义后,使用AsyncTask就比较简单了。

2、基本用法

Android给出的使用示例如下:

//使用时继承AsyncTask,并指定模板参数

privateclassDownloadFilesTaskextendsAsyncTask<

URL,Integer,Long>

{

//后台执行的任务

protectedLongdoInBackground(URL...urls){

intcount=urls.length;

longtotalSize=0;

for(inti=0;

i<

count;

i++){

//下载操作

totalSize+=Downloader.downloadFile(urls[i]);

//更新下载进度

publishProgress((int)((i/(float)count)*100));

//Escapeearlyifcancel()iscalled

//若主动结束AsyncTask,则结束任务

if(isCancelled())break;

}

returntotalSize;

protectedvoidonProgressUpdate(Integer...progress){

//UI线程更新进度

setProgressPercent(progress[0]);

protectedvoidonPostExecute(Longresult){

//执行完毕后,UI线程调用

showDialog("

Downloaded"

+result+"

bytes"

);

}

AsyncTask的使用较为简单,对于上面的例子,可以按照以下方式使用:

newDownloadFilesTask().execute(url1,url2,url3);

对于APK开发者来说,掌握到这个地方就能满足开发需求了。

不过为了满足我们的好奇心,我们还是进一步看看源码是如何实现的。

3、源码分析

我们主要按照AsyncTask基本用法的流程,来分析AsyncTask的实现。

3.1构造函数

在使用AsyncTask前,会创建出AsyncTask的实例。

实际的子类会调用AsyncTask的构造函数。

AsyncTask的构造函数如下所示:

publicAsyncTask(){

//WorkerRunnable实现Callable接口

//参数类型为Params,接口函数call返回值的类型为Result

mWorker=newWorkerRunnable<

Params,Result>

(){

publicResultcall()throwsException{

//mWorker在call接口中的工作先不分析,后文会提到

................

};

//创建一个FutureTask对象,构造函数的参数为一个callable对象

//当FutureTask执行时,会调用callable对象的call函数,在执行完毕后再回调done接口

mFuture=newFutureTask<

Result>

(mWorker){

@Override

protectedvoiddone(){

//此处done接口中的内容,先不分析后文会提到

从上面的代码可以看出,AsyncTask的构造函数中仅创建出了两个对象。

注意到这两个对象均创建在主线程中。

如果用命令模式来理解的话,那么AsyncTask中仅创建出了一个需要执行的命令。

这个命令还没有被添加到执行队列中。

3.2execute接口

AsyncTask有好几个execute接口,我们分析最常用的接口。

//注解说明了此接口在主线程中调用

@MainThread

publicfinalAsyncTask<

Params,Progress,Result>

execute(Params...params){

//注意到除了传入参数外,还传入了sDefaultExecutor

returnexecuteOnExecutor(sDefaultExecutor,params);

在分析executeOnExecutor流程前,我们看看sDefaultExecutor。

..............

//静态成员,进程共享,默认指向SERIAL_EXECUTOR

//可以调用AsyncTask的setDefaultExecutor进行设置

//因此,设置了volatile属性,保证并发的可见性

privatestaticvolatileExecutorsDefaultExecutor=SERIAL_EXECUTOR;

............

/**

*An{@linkExecutor}thatexecutestasksoneatatimeinserial

*order.Thisserializationisglobaltoaparticularprocess.

*/

//SERIAL_EXECUTOR指向的对象为SerialExecutor

publicstaticfinalExecutorSERIAL_EXECUTOR=newSerialExecutor();

privatestaticclassSerialExecutorimplementsExecutor{

//队列中保存所有的任务

finalArrayDeque<

Runnable>

mTasks=newArrayDeque<

();

//mActive中保存当前正在执行的任务

RunnablemActive;

publicsynchronizedvoidexecute(finalRunnabler){

//execute函数被调用时,将runable对象加入到mTasks中

mTasks.offer(newRunnable(){

//当该runnable被执行后,调用scheduleNext

publicvoidrun(){

try{

r.run();

}finally{

scheduleNext();

});

//当有新加入的任务时,若当前没有正在处理的任务,则直接调用scheduleNext接口

if(mActive==null){

protectedsynchronizedvoidscheduleNext(){

//从队列中取出第一个任务

if((mActive=mTasks.poll())!

=null){

//利用THREAD_POOL_EXECUTOR执行

//根据execute中的定义,我们知道一个runable的run方法结束后

//才会重新调用scheduleNext

//因此,虽然THREAD_POOL_EXECUTOR可以同时创建多个线程

//但AsyncTask还是一个接一个的处理任务

//如果将本函数的if改成while,就是并发处理了

THREAD_POOL_EXECUTOR.execute(mActive);

THREAD_POOL_EXECUTOR为AsyncTask加载时创建出的ThreadPoolExecutor,

由于SerialExecutor限制任务必须单一依次执行,因此我们不再关注THREAD_POOL_EXECUTOR的参数。

3.3executeOnExecutor接口

现在我们将视线拉回到executeOnExecutor接口。

executeOnExecutor(Executorexec,

Params...params){

//AsyncTask中定义了:

privatevolatileStatusmStatus=Status.PENDING;

//因此每个AsyncTask对象创建后,其状态都是PENDING

//这里就是文档中叙述的,每个AsyncTask只能运行一次的原因

if(mStatus!

=Status.PENDING){

switch(mStatus){

caseRUNNING:

thrownewIllegalStateException("

Cannotexecutetask:

"

+"

theskisalreadyrunning."

caseFINISHED:

thetaskhasalreadybeenexecuted"

(ataskcanbeexecutedonlyonce)"

//AsyncTask开始运行后,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 中国风

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1