前言
我们都知道在主线程和子线程之间的通信主要依靠Handler完成,但子线程无法直接对主线程的组件进行更新,在android1.5后提供了一个android.os.AsyncTask(非同步任务)类,我们可以通过此类完成非阻塞的操作类。该类和Handler类似,可以在后台进行操作之后更新主线程的UI,但它的使用要比Handler容易许多。
正文
AsyncTask是异步任务,那么为什么要有异步任务
我们首先就需要知道Android是单线程模型(关于何为单线程,请看这里),还有就是我们要知道Android要求耗时操作不可以在主线程中执行。由此我们必须想到相对应得解决办法。AsyncTask由此而生。
它可以在子线程中去更新我们的UI,封装、简化异步操作。
android.os.AsyncTask类的继承结构如下:
java.lang.Object
===>android.os.AsyncTask<Params,Progress,Result>
AsyncTask<Params,Progress,Result>是一个抽象类,而抽象类需要被继承,继承AsyncTask需要指定如下三个泛型参数:
- Params:启动时需要的参数类型,如每次操作的休眠时间为Integer。
- Progress:后台执行任务的百分比,如进度条需要传递的是Integer。
- Result:后台执行完毕之后返回的信息,如完成数据信息显示传递的是String。
android.os.AsyncTask类中定义的常用方法:
1.public final boolean cancel(boolean mayInterruptIfRunning) 普通类型 指定是否取消当前线程操作
2.public final AsyncTask<Params,Progress,Result> execute(Params...params) 普通类型 执行AsyncTask操作
3.public final boolean isCancelled() 普通类型 判断子线程是否被取消
4.public final void publishProgress(Progress...values) 普通 更新线程进度
5.protected abstract Result doInBackground(Params...params) 普通类型 在后台完成任务执行,可以调用publishProgress()方法更新线程进度
6.protected void onProgressUpdate(Progress...values) 普通类型 在主线程中执行,用于显示任务的进度
7.protected void onPreExecute() 普通类型 在主线程中执行,在doInBackground()之前执行
8.protected void onPostExecute(Result result) 普通类型 在主线程中执行,方法参数为任务执行结果
9.protected void onCancelled() 普通类型 在主线程中执行,在cancel()方法之后执行
上面介绍了我们的AsyncTask常用的方法,但在实际开发中,更多的是覆写如写几个方法:
- doInBackground:必须重写,异步执行后台线程将要完成的任务
- onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化操作
- onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法返回的值传给该方法
- onProgressUpdate:在doInBackground()方法中调用publishProgress()方法,更新任务的执行进度后,就会触发该方法
一个简单的案例:使用AsyncTask类完成一个进度条的增长处理。
1.布局文件
2.Activity程序
到这里为止一个简单的案例就算好了。我在练习时,因为对线程的理解不够,导致自己最开始把该放在UI主线程的程序,就是它
放在了子线程中,导致studio一直报错:Method...must be called from UI Thread,currently inferred thread is worker。
我们也可以试着去打印Log来观察异步执行的顺序:
onPreExecute => doInBackground => onProgressUpdate => onPostExecute
这里我多写一些东西,关于Android主线程的。
Android主线程也叫UI线程。它是非UI安全的。(也就是说非UI线程去修改UI线程会有问题)
Android中动态的修改UI线程中的UI,常用的方法有5种:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable,long)
- Handler
- AsyncTask
AsyncTask注意事项:
- 必须在UI线程中创建AsyncTask的实例(onCrete()方法中)
- 必须在UI线程中调用AsyncTask的exceute()方法
- 每个AsyncTask只能被执行一次