AsyncTask是什么

本文介绍了Android中实现异步任务的两种方式:Handler和AsyncTask。重点讲解了AsyncTask的使用方法,包括创建子类、指定泛型参数、重写回调方法等。并提供了注意事项,帮助开发者更好地理解和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Android中实现异步任务机制有两种方式,Handler和AsyncTask。Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制,AsyncTask,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务。

AsyncTask是定义异步任务在后台线程(子线程中)运行的,而结果更新UI在UI线程中,接收三个参数,Params(传入的值)Progress(进度) Result(返回的结果),有四步onPreExecute(在UI线程中执行,准备操作)doInBackground(子线程中耗时操作)onProgressUpdate (进度更新)onPostExecute(结果返回)

来看下executeOnExecutor()方法:

 @MainThread(主线程中调用的)
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
      //这里有一些异常的判断 ,由于代码量多,我就去掉了,在这里我们不考虑异常问题

        //在这里首先吧状态给位RUNNING
        mStatus = Status.RUNNING;
        //执行前的准备工作
        onPreExecute();
        //这里的params就是我们传入的值,然后赋值给了mWorker,那么我们就要看看这个是什么意思了
        mWorker.mParams = params;
        //用线程池执行这个future
        exec.execute(mFuture);
        //最终返回自己
        return this;
    }

首先AsyncTask是一个抽象类,必须要创建它的子类。但是在继承AsyncTask类的时候,需要指定三个泛型参数。解释分别如下:

(1)Params

在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。

(2)Progress

后台任务在执行时,如果需要在界面上显示当前进度,则就用Progress指定的泛型作为进度单位。

(3)Result

当后台任务执行完毕后,如果需要对结果进行返回,那么就用这里指定的泛型作为返回的类型。

然后一般在子类中,需要重写下面的几个回调方法,他们都是自动被调用的,不要在代码中人工调用。

(1)onPreExexute()

该方法在后台任务执行前,即doInBackground方法执行前被调用。通常在这里执行一些初始化的操作,比如显示一个进度条。

(2)doInBackground(Params...)

该方法用来执行后台任务,它的所有代码都是在子线程中操作,任务一旦完成就会用return来返回结果。当然它的参数和返回结果的类型就是上面我们所指定的Params和Result。千万注意,不要在这个

方法中执行更新UI的操作。如果需要更新UI元素,比如说反馈当前任务的进度,可以调用publishProgress(Progress...)方法来完成。

(3)onProgressUpdate(Progress...)

当在后台任务中调用了publishProgress方法后,就会自动调用该方法,方法中的参数就是publishProgress方法传递过来的。这个方法可以对UI进行更新。

(4)onPostExecute(Result)

当后台任务执行完毕,即doInBackground执行完毕后,该方法被调用。doInBackground返回的结果就是该方法的参数,这这里可以执行任务完成后的逻辑,比如说关闭一个进度条,更新一些UI等。

需要说明的是这几个方法,只有doInBackground方法是在子线程中执行的,其他的都是在主线程中执行的。那么启动和取消这个任务的方法是什么呢?如下:

myAsyncTask.execute()其中该任务

yAsyncTask.cancel()取消该任务

Android AsyncTask注意事项

1. AsyncTask对象不可重复使用,也就是说一个AsyncTask对象只能execute()一次,否则会有异常抛出"java.lang.IllegalStateException: Cannot execute task: the task is already running"

2. 在doInBackground()中要检查isCancelled()的返回值,如果你的异步任务是可以取消的话。cancel()仅仅是给AsyncTask对象设置了一个标识位,当调用了cancel()后,发生的事情只有:AsyncTask对象的标识位变了,和doInBackground()执行完成后,onPostExecute()不会被回调了,而doInBackground()和 onProgressUpdate()还是会继续执行直到doInBackground()结束。所以要在doInBackground()中不断的检查 isCancellled()的返回值,当其返回true时就停止执行,特别是有循环的时候。如上面的例子,如果把读取数据的isCancelled() 检查去掉,图片还是会下载,进度也一直会走,只是最后图片不会放到UI上(因为onPostExecute()没被回调)!这里的原因其实很好理解,想想Java SE的Thread吧,是没有方法将其直接Cacncel掉的,那些线程取消也无非就是给线程设置标识位,然后在run()方法中不断的检查标识而已。

3. 如果要在应用程序中使用网络,一定不要忘记在AndroidManifest中声明INTERNET权限,否则会报出很诡异的异常信息,比如上面的例子,如果把INTERNET权限拿掉会抛出"UnknownHostException"。刚开始很疑惑,因为模拟器是可以正常上网的,后来Google了下才发现原来是没权限,但是疑问还是没有消除,既然没有声明网络权限,为什么不直接提示无网络权限呢?对比Java SE的Thread Thread是非常原始的类,它只有一个run()方法,一旦开始,无法停止,它仅适合于一个非常独立的异步任务,也即不需要与主线程交互,对于其他情况,比如需要取消或与主线程交互,都需添加额外的代码来实现,并且还要注意同步的问题。而AsyncTask是封装好了的,可以直接拿来用,如果你仅执行独立的异步任务,可以仅实现doInBackground()。

所以,当有一个非常独立的任务时,可以考虑使用Thread,其他时候,尽可能的用 AsyncTask。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值