**AsyncTask子类的泛型参数:
AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承.继承AsyncTask需要指定如下三个泛型参数:
Params:启动任务时输入的参数类型.
Progress:后台任务执行中返回进度值的类型.
Result:后台任务执行完成后返回结果的类型.
**AsyncTask子类的回调方法:
doInBackground:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.
onPreExecute:执行后台耗时操作前被调用,通常用于进行初始化操作.
onPostExecute:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法.通过此方法进行UI的更新.
onProgressUpdate:当在doInBackground方法中调用publishProgress()方法更新任务执行进度后,将调用此方法.通过此方法我们可以知晓任务的完成进度.
**使用AsyncTask的注意事项:
① 必须在UI线程(create()中)中创建AsyncTask的实例.
② 只能在UI线程中调用AsyncTask的execute方法.
③ AsyncTask被重写的四个方法是系统自动调用的,不应手动调用.
④ 每个AsyncTask只能被执行(execute方法)一次,多次执行将会引发异常.
⑤ AsyncTask的四个方法,只有doInBackground方法是运行在其他线程中,其他三个方法都运行在UI线程中,也就说其他三个方法都可以进行UI的更新操作.
例子:
activity_main.xml:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 11 <Button 12 android:id="@+id/btn_progress" 13 android:layout_width="match_parent" 14 android:layout_height="wrap_content" 15 android:text="进度条加载" /> 16 17 </RelativeLayout>
progress.xml文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" 4 android:layout_width="match_parent" 5 android:gravity="center" 6 android:layout_height="match_parent"> 7 <ProgressBar 8 style="?android:attr/progressBarStyleHorizontal" 9 android:id="@+id/progress" 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content"/> 12 </LinearLayout>
Java代码:
1 package com.example.caobotao.learnasynctask; 2 3 import android.app.Activity; 4 import android.os.AsyncTask; 5 import android.os.AsyncTask.Status; 6 import android.os.Bundle; 7 import android.widget.ProgressBar; 8 9 import java.util.Scanner; 10 11 /** 12 * Created by caobotao on 15/12/2. 13 */ 14 public class ProgressActivity extends Activity{ 15 private ProgressBar progressBar; 16 private MyAsyncTask myAsyncTask; 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.progress); 21 progressBar = (ProgressBar) findViewById(R.id.progress); 22 myAsyncTask = new MyAsyncTask(); 23 //启动异步任务的处理 24 myAsyncTask.execute(); 25 } 26 27 //AsyncTask是基于线程池进行实现的,当一个线程没有结束时,后面的线程是不能执行的. 28 @Override 29 protected void onPause() { 30 super.onPause(); 31 if (myAsyncTask != null && myAsyncTask.getStatus() == Status.RUNNING) { 32 //cancel方法只是将对应的AsyncTask标记为cancelt状态,并不是真正的取消线程的执行. 33 myAsyncTask.cancel(true); 34 } 35 } 36 37 class MyAsyncTask extends AsyncTask<Void,Integer,Void>{ 38 @Override 39 protected void onProgressUpdate(Integer... values) { 40 super.onProgressUpdate(values); 41 //通过publishProgress方法传过来的值进行进度条的更新. 42 progressBar.setProgress(values[0]); 43 } 44 45 @Override 46 protected Void doInBackground(Void... params) { 47 //使用for循环来模拟进度条的进度. 48 for (int i = 0;i < 100; i ++){ 49 //如果task是cancel状态,则终止for循环,以进行下个task的执行. 50 if (isCancelled()){ 51 break; 52 } 53 //调用publishProgress方法将自动触发onProgressUpdate方法来进行进度条的更新. 54 publishProgress(i); 55 try { 56 //通过线程休眠模拟耗时操作 57 Thread.sleep(300); 58 } catch (InterruptedException e) { 59 e.printStackTrace(); 60 } 61 } 62 return null; 63 } 64 } 65 }
存在问题:
AsyncTask是基于线程池进行实现的,当一个线程没有结束时,后面的线程是不能执行的.所以必须等到第一个task的for循环结束后,才能执行第二个task.我们知道,当点击BACK键时会调用Activity的onPause()方法.为了解决这个问题,我们需要在Activity的onPause()方法中将正在执行的task标记为cancel状态,在doInBackground方法中进行异步处理时判断是否是cancel状态来决定是否取消之前的task.