AsyncTask使用注意点

郭神从源码角度分析了AsyncTask的原理和使用http://blog.csdn.net/guolin_blog/article/details/11711405
我从API中看到了其他的一些需要注意的内容,顺手也做一下记录(以android21版本api为例):
我们打开android api ,在android.os路径下找到AsyncTask类,或者打开AsyncTask的源码查看AsyncTask的注释说明。
由于个人英文水平有限,译文仅供参考。
关于AsyncTask的api第二段即提示我们:

AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

AsyncTask比较理想的使用情况是执行短时间的任务(至多数秒钟即可执行完毕)。如果你需要保持工作线程长时间处于运行状态,强烈推荐你使用java.util.concurrent包下提供的工具例如:Executor,ThreadPoolExecutor和FutureTask。

然后是AsyncTask的4个阶段方法介绍:

The 4 steps

When an asynchronous task is executed, the task goes through 4 steps:

当一个异步任务执行时,该任务会经历4个阶段:

onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.

1.onPreExecute()阶段:在任务执行前,在UI线程会调用该方法。通常,在这一阶段时设置该任务,例如:在界面显示一个进度条。

doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.

2.doInBackground()阶段;在阶段1执行完毕后,会在后台工作线程立即调用该方法,。该方法用于后台线程执行长时间的计算操作。异步任务的参数通过该方法传递进去。计算结果必须通过该方法反馈回,并被传递到最后一个阶段。
在该阶段,也可以通过调用publishProgress方法来公布执行进度,调用publishProgress方法会触发onProgressUpdate()回调方法,并在onProgressUpdate()方法中获取到这些公布的进度值。

onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.

3.onProgressUpdate()阶段:在执行publishProgress()方法后会调用该方法,它的执行时间是不确定的(只要调用publishProgress方法juicer会触发调用onProgressUpdate方法在UI线程执行刷新)。该方法用于当后台线程仍旧处于执行过程中时,在界面展示任何形式的进度。例如:它可以用于展示一个进度条动画或者在文本控件上展示log内容。

onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

onPostExecute()阶段:在后台线程执行完毕后在UI主线程会调用该方法,后台计算结果数据将作为参数传递到该方法中。
然后,我们继续往下看:google大神告知我们该类的线程规则:

Threading rules

There are a few threading rules that must be followed for this class to work properly:

    The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
    The task instance must be created on the UI thread.
    execute(Params...) must be invoked on the UI thread.
    Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
    The task can be executed only once (an exception will be thrown if a second execution is attempted.)

说了那么多,或许还是有点蒙,那些参数都是咋回事,有些示例都使用同一种参数,看蒙了。好吧,那么我们从源码来看看这些参数是怎么回事。怎么看呢,很简单,我们把上面说的几个阶段方法完整列出来相信你就直接明白了。
我们将这几个阶段方法完整的列出来,就可以知道其中的奥秘了。

我们先列出AsyncTask需要的参数:

public abstract class AsyncTask<Params, Progress, Result> {}

看到abstract就知道,这个工具类必须要子类实现才能使用。
传递了 Params,Progress和Result三个参数。
1.第一个阶段方法:

protected void onPreExecute() {}

这个方法为无参,返回类型为void。跟上述三个参数没有半毛钱关系。
2.第二个阶段方法:

protected abstract Result doInBackground(Params... params);

抽象方法,传递了我们的第一个参数的参数类型Params,但是是个变长参数,是个数组。查看各种示例,基本上用到的就是params[0],这个抽象方法反馈的结果为Result参数的数据类型。
3.第二阶段的通知刷新方法:

 protected final void publishProgress(Progress... values) {
    }

传递参数为Progress类型的参数,反馈为void。
参考各种示例,我们不难发现,这个Progress参数是我们在doInBackground方法中计算出的一个进度值,通常也就是Integer类型。
4.第三阶段方法:

protected void onProgressUpdate(Progress... values) {
    }

这个界面ui刷新方法完全接收publishProgress传递的参数,实际上仍旧是使用到这个变长参数的第一个数据:values[0]
5.第四阶段方法

 protected void onPostExecute(Result result) {
    }

按照api中所说,doInBackground方法反馈的Result型数据会直接的传递到该阶段方法中。
也就是说onPostExecute的参数result就是doInBackground方法返回的数据。

从上面几点可以看出,
Params类型参数是供doInBackground工作线程处理时使用,看实际需求情况,可能用不到,使用void。
Progress类型参数供刷新过程中使用publishProgress,onProgressUpdate,一般也就是用来显示进度值的Integer类型;
Result类型参数是供doInBackground和onPostExecute任务处理完毕时才使用的数据类型。至于实际类型,可能用不到,可以使用void。

线程规则:

为了能够让AsyncTask类正常工作,以下是必须要遵守的一些线程规则:
1.AsyncTask类必须要在UI线程中加载,在JELLY_BEAN版本,这个操作是自动执行的。
2.AsyncTask实例必须要在UI线程创建,实例执行方法execute()方法必须要在UI线程调用
3.不要手动调用AsyncTask的4个周期方法:onPreExecute,onPostExecute,doInBackground,onProgressUpdate。(也就是说,我们需要在继承自AsyncTask的子类中将我们需要的具体操作在这些回调方法中实现)
4.这个任务只能执行一次(试图第二次执行该任务实例会抛出异常)。
那么,我们只能在每次需要执行的时候都必须通过重新创建实例并执行execute方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值