AsyncTask应用

**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.

原文地址:https://www.cnblogs.com/solar-sys/p/6004943.html