一、AsyncTask介绍
上一篇博客介绍了多线程handle的使用,但是handle需要通过post或sendMessage来使用handle通知主线程来更新UI,我们需要完成子线程和handle的内部实现,而AsyncTask封装了所有,我们只需要继承AsyncTask类,在类里面根据自己的需求重写相对应函数,需要在主线程执行的函数也在类里面重写,不需要我们重新在类外写函数接受信息,比起“Thread+handle”的组合简便了很多。
二、AsyncTask使用
1. 函数介绍
execute函数,子线程启动函数,子线程实例化后必须使用asynctask.execute()才可以启动子线程,可带参数
AsynaTask是个抽象类,我们使用时必须继承它,然后根据需要重写相关函数
(1)抽象类
public class MyAsyncTask extends AsyncTask<Params, Progress, Result >{}
三个参数为泛型类型,第一个参数为子线程启动时传入的参数,第二个参数为子线程处理过程中(还未结束,比如更新进度条)进行更新UI传递的参数,第三个参数是子线程处理完之后返回主线程的参数,如果不需要参数,只需要将其设为void。
(2)类中相关函数
- doInBackground(Params[] params),子线程的处理操作,如果Result存在,比如第三个参数为String类型,则返回类型也为String,返回的数据将在下一个函数接收到。
- onPostExecute(Result result),子线程结束后在主线程进行的操作,比如对UI进行更新,其中所带参数为doInBackground返回的类型。
- onPreExecute(),子线程开始时的准备工作
- onProgressUpdate(Progress[] progress),子线程执行过程中对UI的更新,比如即时更新进度条。参数为类中第二个参数。
- onCancelled(),打断当前子线程,直接调用该函数,这样子线程就不会调用onPostExecute函数了。但该方法对IO操作无作用。
- publishProgress(Progress progress),可以写在doInBackground函数中的一个方法,用于在子线程执行过程中将数据发送给onProgressUpdate,从而进行UI的更新。注意:该方法只能写在doInBackground。
(3)对象调用的方法
- execute(Params[] params),实例化一个对象之后,调用该方法,启动子线程,可以传递数据。
- executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params[] params),这也是对象调用的方法来启动子线程,这也可以传递数据,与上一条差别后面讲。
- cancel(true),进而会调用onCancelled来结束当前子线程。
2. 类里面函数搭配
(1)最基本实用
doInBackground+onPostExecute,这两个函数是必须重写的,只实现简单的多线程操作就可以用这个搭配
(2)需要在子线程执行过程中更新UI
doInBackground+onPostExecute+onProgressUpdate+publishProgress(在doInBackground中使用)
(3)需要在子线程启动前做准备工作
[(2)|(1)] + onPreExecute
(4)可以手动停止子线程
[(2)|(1)|(3)]+onCancelled
3. 使用步骤
(1)继承AsyncTask类,并根据需求重写相对应函数
(2)实例化一个对象,可传递数据
(3)对象调用execute或者executeOnExecutor启动子线程
(4)如果需要,调用cancel(true)
三、串行与并行
- 一个对象只能execute一次,所以使用try+catch来防止出发两次。
- 一个AsyncTask的类的不同对象(无论是不是同一个类,只要继承类AsyncTask),默认情况(使用execute)是串行执行的,比如你同时对两个子线程对象调用execute,两个子线程并不会同时执行,而是串行方法。
- 如何并行:使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,Params[] params)来启动子线程,这时候子线程(不同对象)就是并行的。
- 并行串行选择:并行执行可以不用等上一个AsyncTask对象执行完就可以执行,但如果对同一个UI进行更新,会造成混乱。
四、AsyncTask内存泄露
和上一篇一样,这里不多讲
- 将AsyncTask类声明为static内部类
- 手动将子线程全部移除
- 在destory使用cancel(boolean),会打断当前子线程,这样就不会调用onPostExecute,而是调用onCanclled。对IO操作不起作用。