Android中AsyncTask使用详解_asynctack-程序员宅基地

技术标签: Android中AsyncTask使用详  Android  

在Android中我们可以通过Thread+Handler实现多线程通信,一种经典的使用场景是:在新线程中进行耗时操作,当任务完成后通过Handler向主线程发送Message,这样主线程的Handler在收到该Message之后就可以进行更新UI的操作。上述场景中需要分别在Thread和Handler中编写代码逻辑,为了使得代码更加统一,我们可以使用AsyncTask类。

AsyncTask是Android提供的一个助手类,它对Thread和Handler进行了封装,方便我们使用。Android之所以提供AsyncTask这个类,就是为了方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行UI更新等操作。在使用AsyncTask时,我们无需关注Thread和Handler,AsyncTask内部会对其进行管理,这样我们就只需要关注于我们的业务逻辑即可。

AsyncTask有四个重要的回调方法,分别是:onPreExecute、doInBackground, onProgressUpdate 和 onPostExecute。这四个方法会在AsyncTask的不同时期进行自动调用,我们只需要实现这几个方法的内部逻辑即可。这四个方法的一些参数和返回值都是基于泛型的,而且泛型的类型还不一样,所以在AsyncTask的使用中会遇到三种泛型参数:Params, Progress 和 Result,如下图所示: 
这里写图片描述

  • Params表示用于AsyncTask执行任务的参数的类型
  • Progress表示在后台线程处理的过程中,可以阶段性地发布结果的数据类型
  • Result表示任务全部完成后所返回的数据类型

我们通过调用AsyncTask的execute()方法传入参数并执行任务,然后AsyncTask会依次调用以下四个方法:

  • onPreExecute 
    该方法的签名如下所示: 
    这里写图片描述 
    该方法有MainThread注解,表示该方法是运行在主线程中的。在AsyncTask执行了execute()方法后就会在UI线程上执行onPreExecute()方法,该方法在task真正执行前运行,我们通常可以在该方法中显示一个进度条,从而告知用户后台任务即将开始。

  • doInBackground 
    该方法的签名如下所示: 
    这里写图片描述 
    该方法有WorkerThread注解,表示该方法是运行在单独的工作线程中的,而不是运行在主线程中。doInBackground会在onPreExecute()方法执行完成后立即执行,该方法用于在工作线程中执行耗时任务,我们可以在该方法中编写我们需要在后台线程中运行的逻辑代码,由于是运行在工作线程中,所以该方法不会阻塞UI线程。该方法接收Params泛型参数,参数params是Params类型的不定长数组,该方法的返回值是Result泛型,由于doInBackgroud是抽象方法,我们在使用AsyncTask时必须重写该方法。在doInBackground中执行的任务可能要分解为好多步骤,每完成一步我们就可以通过调用AsyncTask的publishProgress(Progress…)将阶段性的处理结果发布出去,阶段性处理结果是Progress泛型类型。当调用了publishProgress方法后,处理结果会被传递到UI线程中,并在UI线程中回调onProgressUpdate方法,下面会详细介绍。根据我们的具体需要,我们可以在doInBackground中不调用publishProgress方法,当然也可以在该方法中多次调用publishProgress方法。doInBackgroud方法的返回值表示后台线程完成任务之后的结果。

  • onProgressUpdate 
    上面我们知道,当我们在doInBackground中调用publishProgress(Progress…)方法后,就会在UI线程上回调onProgressUpdate方法,该方法的方法签名如下所示: 
    这里写图片描述 
    该方法也具有MainThread注解,表示该方法是在主线程上被调用的,且传入的参数是Progress泛型定义的不定长数组。如果在doInBackground中多次调用了publishProgress方法,那么主线程就会多次回调onProgressUpdate方法。

  • onPostExecute 
    该方法的签名如下所示: 
    这里写图片描述 
    该方法也具有MainThread注解,表示该方法是在主线程中被调用的。当doInBackgroud方法执行完毕后,就表示任务完成了,doInBackgroud方法的返回值就会作为参数在主线程中传入到onPostExecute方法中,这样就可以在主线程中根据任务的执行结果更新UI。

下面我们就以下载多个文件的示例演示AsyncTask的使用过程。

布局文件如下所示:

<code class="hljs perl has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><RelativeLayout xmlns:android=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://schemas.android.com/apk/res/android"</span>
    xmlns:tools=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://schemas.android.com/tools"</span>
    android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span>
    android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span>
    android:paddingLeft=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@dimen</span>/activity_horizontal_margin"</span>
    android:paddingRight=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@dimen</span>/activity_horizontal_margin"</span>
    android:paddingTop=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@dimen</span>/activity_vertical_margin"</span>
    android:paddingBottom=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@dimen</span>/activity_vertical_margin"</span>
    tools:context=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">".MainActivity"</span>>

    <Button android:id=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@+</span>id/btnDownload"</span>
        android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span>
        android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span>
        android:onClick=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"onClick"</span>
        android:text=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"开始下载"</span> />

    <TextView android:id=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@+</span>id/textView"</span>
        android:layout_below=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@id</span>/btnDownload"</span>
        android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span>
        android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span> />

<<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">/RelativeLayout></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>

界面上有一个“开始下载”的按钮,点击该按钮即可通过AsyncTask下载多个文件,对应的Java代码如下所示:

<code class="hljs axapta has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">package com.ispring.asynctask;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MainActivity</span> <span class="hljs-inheritance" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span></span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> <span class="hljs-inheritance" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span></span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Button</span>.<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnClickListener</span> {</span>

    TextView textView = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
    Button btnDownload = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;

    @Override
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onCreate(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView)findViewById(R.id.textView);
        btnDownload = (Button)findViewById(R.id.btnDownload);
        Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iSpring"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"MainActivity -> onCreate, Thread name: "</span> + Thread.currentThread().getName());
    }

    @Override
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onClick(View v) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//要下载的文件地址</span>
        String[] urls = {
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47115879"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47180325"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47300819"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47320407"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47622705"</span>
        };

        DownloadTask downloadTask = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DownloadTask();
        downloadTask.execute(urls);
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//public abstract class AsyncTask<Params, Progress, Result></span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在此例中,Params泛型是String类型,Progress泛型是Object类型,Result泛型是Long类型</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DownloadTask</span> <span class="hljs-inheritance" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span></span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AsyncTask</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">String</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Object</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Long</span>> {</span>
        @Override
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onPreExecute() {
            Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iSpring"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"DownloadTask -> onPreExecute, Thread name: "</span> + Thread.currentThread().getName());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onPreExecute();
            btnDownload.setEnabled(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);
            textView.setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"开始下载..."</span>);
        }

        @Override
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> Long doInBackground(String... params) {
            Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iSpring"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"DownloadTask -> doInBackground, Thread name: "</span> + Thread.currentThread().getName());
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//totalByte表示所有下载的文件的总字节数</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> totalByte = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//params是一个String数组</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(String url: params){
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//遍历Url数组,依次下载对应的文件</span>
                Object[] result = downloadSingleFile(url);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> byteCount = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)result[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                totalByte += byteCount;
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在下载完一个文件之后,我们就把阶段性的处理结果发布出去</span>
                publishProgress(result);
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果AsyncTask被调用了cancel()方法,那么任务取消,跳出for循环</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(isCancelled()){
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
                }
            }
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将总共下载的字节数作为结果返回</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> totalByte;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//下载文件后返回一个Object数组:下载文件的字节数以及下载的博客的名字</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Object[] downloadSingleFile(String <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">str</span>){
            Object[] result = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Object[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> byteCount = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            String blogName = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
            HttpURLConnection conn = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>{
                URL url = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> URL(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">str</span>);
                conn = (HttpURLConnection)url.openConnection();
                InputStream is = conn.getInputStream();
                ByteArrayOutputStream baos = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayOutputStream();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] buf = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024</span>];
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> length = -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> ((length = is.read(buf)) != -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) {
                    baos.write(buf, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, length);
                    byteCount += length;
                }
                String respone = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> String(baos.toByteArray(), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"utf-8"</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> startIndex = respone.indexOf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<title>"</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(startIndex > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
                    startIndex += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>;
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> endIndex = respone.indexOf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"</title>"</span>);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(endIndex > startIndex){
                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解析出博客中的标题</span>
                        blogName = respone.substring(startIndex, endIndex);
                    }
                }
            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(MalformedURLException e){
                e.printStackTrace();
            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(IOException e){
                e.printStackTrace();
            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(conn != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){
                    conn.disconnect();
                }
            }
            result[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = byteCount;
            result[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = blogName;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> result;
        }

        @Override
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onProgressUpdate(Object... values) {
            Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iSpring"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"DownloadTask -> onProgressUpdate, Thread name: "</span> + Thread.currentThread().getName());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onProgressUpdate(values);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> byteCount = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)values[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            String blogName = (String)values[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
            String text = textView.getText().toString();
            text += <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\n博客《"</span> + blogName + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"》下载完成,共"</span> + byteCount + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"字节"</span>;
            textView.setText(text);
        }

        @Override
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onPostExecute(Long aLong) {
            Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iSpring"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"DownloadTask -> onPostExecute, Thread name: "</span> + Thread.currentThread().getName());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onPostExecute(aLong);
            String text = textView.getText().toString();
            text += <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\n全部下载完成,总共下载了"</span> + aLong + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"个字节"</span>;
            textView.setText(text);
            btnDownload.setEnabled(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        }

        @Override
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onCancelled() {
            Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iSpring"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"DownloadTask -> onCancelled, Thread name: "</span> + Thread.currentThread().getName());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCancelled();
            textView.setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"取消下载"</span>);
            btnDownload.setEnabled(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        }
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li></ul>

点击下载按钮后,界面如下所示: 
这里写图片描述

控制台输出如下所示: 
这里写图片描述

下面对以上代码进行一下说明。

  1. 我们在MainActivity中定义了内部类DownloadTask,DownloadTask继承自AsyncTask,在该例中,Params泛型是String类型,Progress泛型是Object类型,Result泛型是Long类型。

  2. 我们定义了一个Url字符串数组,将该数组传递给AsyncTask的execute方法,用于异步执行task。

  3. 在执行了downloadTask.execute(urls)之后,AsyncTask会自动回调onPreExecute方法,在该方法中我们将textView设置为“开始下载…”几个字,告知用户即将执行下载操作。通过控制台输出我们也可以看出该方法是在主线程中执行的。

  4. 在执行了onPreExecute方法之后,AsyncTask会回调doInBackground方法,该方法中的输入参数是String类型的不定长数组,此处的String就对应着Params泛型类型,我们在该方法中遍历Url数组,依次下载对应的文件,当我们下载完一个文件,就相当于我们阶段性地完成了一部分任务,我们就通过调用publishProgress方法将阶段性处理结果发布出去。在此例中我们将阶段性的处理结果定义为Object类型,即Progress泛型类型。通过控制台输出我们可以看出doInBackground方法是运行在新的工作线程”AsyncTask #1”中的,AsyncTask的工作线程都是以”AsyncTask #”然后加上数字作为名字。当所有文件下载完成后,我们就可以通过totalSize返回所有下载的字节数,返回值类型为Long,对应着AsyncTask中的Result泛型类型。

  5. 在doInBackground方法中,每当下载完一个文件,我们就会调用publishProgress方法发布阶段性结果,之后AsyncTask会回调onProgressUpdate方法,在此例中,onProgressUpdate的参数为Object类型,对应着AsyncTask中的Progress泛型类型。通过控制台输出我们可以发现,该方法是在主线程中调用的,在该方法中我们会通过textView更新UI,告知用户哪个文件下载完成了,这样用户体验相对友好。

  6. 在整个doInBackground方法执行完毕后,AsyncTask就会回调onPostExecute方法,在该方法中我们再次通过textView更新UI告知用户全部下载任务完成了。

  7. 在通过execute方法执行了异步任务之后,可以通过AsyncTask的cancel方法取消任务,取消任务后AsyncTask会回调onCancelled方法,这样不会再调用onPostExecute方法。

在使用Android的过程中,有以下几点需要注意:

  • AsyncTask的实例必须在主线程中创建。

  • AsyncTask的execute方法必须在主线程中调用。

  • onPreExecute()、onPostExecute(Result),、doInBackground(Params…) 和 onProgressUpdate(Progress…)这四个方法都是回调方法,Android会自动调用,我们不应自己调用。

  • 对于一个AsyncTack的实例,只能执行一次execute方法,在该实例上第二次执行execute方法时就会抛出异常。

通过上面的示例,大家应该熟悉了AsyncTask的使用流程。我们上面提到,对于某个AsyncTask实例,只能执行一次execute方法,如果我们想并行地执行多个任务怎么办呢?我们可以考虑实例化多个AsyncTask实例,然后分别调用各个实例的execute方法,为了探究效果,我们将代码更改如下所示:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//要下载的文件地址</span>
        String[] urls = {
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47115879"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47180325"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47300819"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47320407"</span>,
                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47622705"</span>
        };

        DownloadTask downloadTask1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DownloadTask();
        downloadTask1.execute(urls);

        DownloadTask downloadTask2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DownloadTask();
        downloadTask2.execute(urls);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

在单击了按钮之后,我们实例化了两个DownloadTask,并分别执行其execute方法,运行后界面如下所示: 
这里写图片描述

控制台输出如下所示: 
这里写图片描述

我们观察一下控制台的输出结果,可以发现对于downloadTask1,doInBackground方法是运行在线程“AsyncTask #1”中的;对于downloadTask2,doInBackground方法是运行在线程”AsyncTask #2”中的,此时我们可能会认为太好了,两个AsyncTask实例分别在不同的线程中运行,实现了并行处理。此处真的是并行运行的吗?

我们自己观察控制台输出就可以发现,downloadTask1的doInBackground方法执行后,下载了五个文件,并五次触发了onProgressUpdate,在这之后才执行downloadTask2的doInBackground方法。我们对比上面的GIF图也可以发现,在downloadTask1按照顺序下载完五篇文章之后,downloadTask2才开始按照顺序下载五篇文章。综上所述,我们可以知道,默认情况下如果创建了AsyncTask创建了多个实例,并同时执行实例的各个execute方法,那么这些实例的execute方法并不是并行执行的,是串行执行的,即在第一个实例的doInBackground完成任务后,第二个实例的doInBackgroud方法才会开始执行,然后再执行第三个实例的doInBackground方法… 那么你可能会问,不对啊,上面downloadTask1是运行在”AsyncTask #1”线程中的,downloadTask2是运行在”AsyncTask #2”线程中的,这明明是两个线程啊!其实AsyncTask为downloadTask1开辟了名为”AsyncTask #1”的工作线程,在其完成了任务之后可能就销毁了,然后AsyncTask又为downloadTask2开辟了名为”AsyncTask #2”的工作线程。

AsyncTask在最早的版本中用一个单一的后台线程串行执行多个AsyncTask实例的任务,从Android 1.6(DONUT)开始,AsyncTask用线程池并行执行异步任务,但是从Android 3.0(HONEYCOMB)开始为了避免并行执行导致的常见错误,AsyncTask又开始默认用单线程作为工作线程处理多个任务。

从Android 3.0开始AsyncTask增加了executeOnExecutor方法,用该方法可以让AsyncTask并行处理任务,该方法的方法签名如下所示:

<code class="hljs oxygene has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> AsyncTask<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Params</span>, Progress, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Result</span>> executeOnExecutor (Executor exec, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Params</span>... <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">params</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

第一个参数表示exec是一个Executor对象,为了让AsyncTask并行处理任务,通常情况下我们此处传入AsyncTask.THREAD_POOL_EXECUTOR即可,AsyncTask.THREAD_POOL_EXECUTOR是AsyncTask中内置的一个线程池对象,当然我们也可以传入我们自己实例化的线程池对象。第二个参数params表示的是要执行的任务的参数。

通过executeOnExecutor方法并行执行任务的示例代码如下所示:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(Build.VERSION.SDK_INT >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">11</span>){
            String[] urls = {
                    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47115879"</span>,
                    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47180325"</span>,
                    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47300819"</span>,
                    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47320407"</span>,
                    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://blog.csdn.net/iispring/article/details/47622705"</span>
            };

            DownloadTask downloadTask1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DownloadTask();
            downloadTask1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urls);

            DownloadTask downloadTask2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DownloadTask();
            downloadTask2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urls);
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

我们实例化了两个DownloadTask的实例,然后执行了这两个实例的executeOnExecutor方法,并将AsyncTask.THREAD_POOL_EXECUTOR作为Executor传入,二者都接收同样的Url数组作为任务执行的参数。

点击下载按钮后,运行完的界面如下所示: 
这里写图片描述

控制台输出如下所示: 
这里写图片描述

通过控制台的输出结果我们可以看到,在downloadTask1执行了doInBackground方法后,downloadTask2也立即执行了doInBackground方法。并且通过程序运行完的UI界面可以看到在一个DownloadTask实例下载了一篇文章之后,另一个DownloadTask实例也立即下载了一篇文章,两个DownloadTask实例交叉按顺序下载文件,可以看出这两个AsyncTask的实例是并行执行的。

后面会写文章讲一下AsyncTask的源码实现原理,希望本文对大家使用AsyncTask的使用有所帮助!

相关阅读: 
我的Android博文整理汇总 
Android中Handler的使用 
Android新线程中更新主线程UI中的View方法汇总

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_17007915/article/details/50683835

智能推荐

人体红外传感器HC-SR501_hc sr501工作原理-程序员宅基地

文章浏览阅读1w次,点赞2次,收藏18次。本文记录的是如何用stm32使用HC-SR501。实验平台:野火指南者stm32f103vet6。实验现象:一旦有人体经过,LED会亮红色。HC-SR501 传感器工作原理人体都有恒定的体温,一般在 37 度,所以会发出特定波长 10UM 左右的红外线,被动式红外探头就是靠探测人体发射的 10um 左右的红外,进行工作的。人体发射的 10um 左右。_hc sr501工作原理

微信小程序云开发之创建数据库表和初始化云环境_微信云开发 自动创建表-程序员宅基地

文章浏览阅读1w次,点赞4次,收藏59次。微信小程序云开发创建数据库表1.进入小程序后点击云开发,开启云开发功能。2.开启云开发功能后会进入云开发控制台后点击左上角的数据库,后点击下面的“+”创建数据表。表名随便取,你开心就好,我的表名叫testDatabase。2.创建完表后,点击右侧的“+添加记录”会弹出一个弹窗,这个弹窗就是填写你所需要的字段。看你需要自己定义字段名,字段类型和值。3.一次只能创建一条数据,且每次创建每一条数据的字段名和类型必须一样。创建完后每一条数据都会多一个“_id”字段,这是云开发数据库自动给_微信云开发 自动创建表

使用选项卡创建CSS3 / jQuery跨浏览器下拉菜单-程序员宅基地

文章浏览阅读126次。CSS3/jQuery dropdown menu with tabs tutorial. This is our seventh CSS3 menu. Today we will make dropdown menu with parental tabs (as first level). Part of the work we pass on to the shoulders of jQuer..._./images/tabs/left_memu_1.png

Hypack 2016-2018设置使用测试与相关下载_hypack2016-程序员宅基地

文章浏览阅读2.3k次,点赞2次,收藏9次。Hypack 2016-2018使用测试与相关下载1、hypack 2016、hypack 2017、hypack2018通过现场使用测试,发现64位版本破解无效,32位破解成功。2、Hypack 6.2以前的版本,导航硬件典型配置库文件为nmea.DLL。(配置为nmea.DLL输出WGS84与本地54坐标XY出现错误)3、Hypack 2016-2018版本导航硬件配置库文件应该采用G..._hypack2016

CiteSpace使用入门教程_citespace怎么用-程序员宅基地

文章浏览阅读8.1k次,点赞4次,收藏17次。CiteSpace软件的使用及应用_citespace怎么用

这6种最佳移动自动化测试工具你知道吗?_移动应用测试工具有哪些-程序员宅基地

文章浏览阅读1k次。它还带有一个客户端库的特性,可以托管 Java、Python、C# 等中的锅炉代码,以帮助 QA 更快、更有效地开发测试脚本。testRigor 是超级可靠的,因为它为人类各自创建了一个测试套件,也就是说,它不依赖于 XPath 之类的源。它是一个基于云的移动自动化测试工具,允许用户在各种设备和操作系统版本上以连续的时间间隔快速运行测试。总而言之,它是一个很好的工具,但既不是免费的也不是开源的。ZAPTEST 的卖点是它的投资回报率计算器,它允许像您这样的企业计算这种自动化工具的投资回报率。_移动应用测试工具有哪些

随便推点

Vue用Export2Excel导出excel,多级表头数据_vue导出为多级表头的excel-程序员宅基地

文章浏览阅读5k次,点赞12次,收藏39次。VUE 使用Export2Excel导出数据,以及多级表头最近公司做项目,需要导出数据到excel表格使用到了 element UI ,Export2Excel特此记录,毕竟好记性不如烂笔头不包含修改样式(菜鸟一枚,希望大佬指教点名)直接上代码导出单级表头Html部分:<el-button @click="handleDownload" class="addButton-class">批量导出</el-button>js部分:// 导出数据handleDo_vue导出为多级表头的excel

一次实战中对tp5网站getshell方式的测试-程序员宅基地

文章浏览阅读711次。0x00 前言之前接触tp5的站比较少,只知道利用RCE漏洞getshell的方式。在最近对一个发卡平台渗透的过程中,由于php版本限制,无法直接使用RCE的payload拿shell,于是结合该网站尽可能多的测试一下tp5+php7.1环境下的getshell方法。0x02 正文拿到站点后,访问首页如下测试中,发现是thinkphp的站,报错如下不过看不出来具体版本,不确定是否存在RCE,于是...__method=__construct&method=get&filter[]=call_user_func≥t[]=phpinfo

浮动清除与弹性布局_怎么禁用弹性布局-程序员宅基地

文章浏览阅读1.7k次。浮动清除与弹性布局浮动布局弊端:父元素高度塌陷。https://blog.csdn.net/Victorymh/article/details/95494748清除浮动方式:方法一:设置父元素高度(仅仅只适用于知道子元素具体有多高)方法二:在父元素的最后1个子元素后面添加1个空的div,不需要设置其他任何的样式,只需要设置clear:both;清除左右浮动,让父元素重新计算子元素的高度。在这里插入图片描述方法三:最佳清除浮动解决方案,伪元素(:after)解决方案。这里的clear只是个类名_怎么禁用弹性布局

vue3的代码改成vue2的转换_vue3组件 转 vue2-程序员宅基地

文章浏览阅读8.7k次。vue3<!DOCTYPE html><html><head><meta charset="utf-8"><title>Vue的方法_侠课岛(9xkd.com)</title><script src="https://unpkg.com/vue@next"></script></head><body> <div id="hello-vue" class="_vue3组件 转 vue2

vue2.0与支付个人总结-程序员宅基地

文章浏览阅读275次。最近在使用vue写webapp,app中要求可以实现线上支付,研究了微信H5支付与支付宝H5支付。其中微信H5支付处在内测阶段,需要申请,按照格式写了邮件七个工作日也没得到回复邮件,据说微信H5支付对于单量和交易额有要求,满足要求后才有很大几率开通。支付宝H5支付相对申请较为简单,人工技术客服强大,基本能解决很多问题,不得不说这点还是阿里..._vue2.0 调用app支付

yml配置文件中map的配置-程序员宅基地

文章浏览阅读6.5k次。yml中map的配置文件

推荐文章

热门文章

相关标签