第十六章:异步处理之AsyncTask的应用

前言android

  咱们知道Android的UI主线程主要负责处理用户的按键事件、用户的触屏事件以及屏幕绘图事件等;既然UI老人家都这么忙了,咱们这些开发者确定不能不识趣的去添乱阻塞UI线程什么的,不然UI界面万一中止响应了呢——这不是招骂的节奏么?!因此咱们知道用Handler+Thread的方法,在子线程中处理耗时的任务,任务完成后经过Handler通知UI主线程更新UI界面,皆大欢喜有木有。网络

  但是这样,仍是有某些人以为用Handler+Thread的代码会比较繁琐,固然这个某些人里面包括咱们伟大的谷歌。因此AsyncTask(异步任务)在Android 1.5中横空出世;相对于Handler来讲,因为比较好的封装,AsyncTask显得更加轻量级一点,适用于简单的异步处理;固然使用起来也比较简洁,果真是谷歌的亲儿子!异步

概述ide

  AsyncTask是一个抽象类,一般是被继承的命。AsyncTask的内部会维持一个静态的线程池,每一个后台任务天然也会被提交到线程池中运行,同时也使用Handler+Thread的机制来调用AsyncTask的各个回调方法;回调方法是在主线程运行的,因此该干什么咱们都懂(~ o ~)~zZ(赶忙跟UI界面套近乎呀)。函数

咱们知道AsyncTask<Params, Progress, Result>是抽象类,咱们能够在这里面看出它支持三种泛型:布局

一、Params:咱们的AsyncTask要开始干活时,咱们给他的输入的参数的类型,也就是传递给后台的参数this

二、Progress:AsyncTask向咱们报告它干活进度的参数类型,举个例子就是下载进度的百分比spa

三、Result:后台执行任务完成,返回的结果的参数类型线程

若是某个泛型咱们不须要指定,咱们能够大大方方的指定Void,没事AsyncTask不会伤心滴。code

固然谷歌也帮咱们将AsyncTask的后台任务运行的五种状态,分别是:一、准备运行,二、正在后台运行,三、进度更新,四、完成后台任务,五、取消任务。每种状态在AsyncTask中各有相应的回调方法。

一、准备运行:onPreExecute(),在任务开启时该回调方法当即在UI线程中被调用,同时也是在执行后台耗时操做前被调用;一般该方法用于完成一些初始化工做,好比在界面上显示进度条等。

二、正在后台运行:doInBackground(Params...),该回调函数由后台线程在onPreExecute()方法执行结束后当即调用,重写该方法就是后台线程将要完成的耗时任务;因为是由后台线程调用,因此咱们不能直接在这里更新UI界面,应该使用publishProgress(Progress...)触发回调方法onProgressUpdate(Progress...)进行进度更新;任务计算的结果必须由该函数返回,并被传递到onPostExecute()中。

三、进度更新:onProgressUpdate(Progress...),在doInBackground()中调用publishProgress()方法更新任务的执行进度,将会在主线程中触发该方法,通常用于动态地显示一个进度条。

四、完成后台任务:onPostExecute(Result),当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground()的返回值传递给该方法。

五、取消任务:onCancelled (),在调用AsyncTask的cancel()方法时调用。

案例

参考代码:

复制代码
public class MainActivity extends ActionBarActivity implements OnClickListener{ private Button startdownload; private ProgressBar probar; private TextView tv; private DownTask task; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startdownload = (Button) findViewById(R.id.startdownload); probar = (ProgressBar) findViewById(R.id.probar); tv = (TextView) findViewById(R.id.tv); startdownload.setOnClickListener(this); } @Override public void onClick(View v) { task = new DownTask();//同一个AsyncTask的execute只能调用一次 task.execute("输入参数,可为空");//调用execute后将会回调onPreExecute方法  } class DownTask extends AsyncTask<String, Integer, String>{ @Override//该方法非在主线程运行,可进行耗时操做,不可更新UI界面,其余方法为主线程运行 protected String doInBackground(String... params) {//params为execute输入的参数 for(int i = 1; i <= 100; i++){ try {//模拟下载操做 Thread.sleep(333); publishProgress(i);//传递参数i并触发onProgressUpdate回调方法 } catch (InterruptedException e) { e.printStackTrace(); } } String result = "任务已完成"; return result;//将调用onPostExecute,并将result传给该回调方法  } @Override protected void onPreExecute() {//该回调方法执行完毕后,将会调用doInBackground probar.setMax(100); probar.setProgress(0); tv.setText("开始下载"); } @Override protected void onPostExecute(String result) {//doInBackground结束后回调该方法,结束。 Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show(); tv.setText("下载完成"); } @Override protected void onProgressUpdate(Integer... values) {//通知UI界面更新 probar.setProgress(values[0]); } } }
复制代码

布局文件:

复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/startdownload" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始下载"/> <ProgressBar android:id="@+id/probar" android:layout_width="match_parent" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000000" android:textSize="20sp" /> </LinearLayout>
复制代码

代码讲解:

一、点击Button后先实例化一个AsyncTask的继承子类,此时将会建立一个task。接下来变执行execute(params)方法启动异步任务。(同一个AsyncTask的实例只能执行execute一次,屡次执行会抛出错误)。

二、在execute()被执行后,将会触发onPreExecute()回调方法,设置进度条的初始属性。在onPreExecute()执行完毕后,将会在后台线程开始执行doInBackground(params),该方法接收execute传入的参数,进行耗时操做,这里是模拟网络文件下载任务。

三、doInBackground()在后台线程运行中,若是须要与UI主线程交互更新进度,能够调用publishProgress(values)方法,将会触发位于UI主线程运行的onProgressUpdate(values)的回调方法,代码中在这里更新进度条的进度。

四、 当后台任务执行完成后,调用onPostExecute(Result),传入的参数是doInBackground()中返回的对象。

注意事项

一、不要在同一个AsyncTask实例中屡次执行execute(),正确的方法是new一个AsyncTask执行一次execute()。

二、耗时任务必定要在doInBackground()中处理,不要在其余回调方法中处理耗时任务以避免引发UI主线程的阻塞。

三、不要再doInBackground()中更新UI界面,应该经过publishProgress()调用回调方法更新UI。

四、onCancelled()只能触发AsyncTask的cancel()方法,并没有法取消正在线程池运行的线程任务,但能够经过标志位来中止线程任务。

五、在不一样的android版本中,AsyncTask多任务运行,有些是能够并行有些则是顺序执行,不过在高版本Android中,能够经过指定参数设置线程池执行规则。

六、AsyncTask适合处理短期的操做,长时间的操做,好比下载一个很大的视频,这就须要你使用本身的线程来下载,不论是断点下载仍是其它的。

相关文章
相关标签/搜索