Android 多线程之 AsyncTask使用源码分析

Android 多线程之 AsyncTask使用源码分析

一、前言

这主要是一个讲解 Android 中多线程的系列,全部文章如下:

上篇文章对 HandlerThread 的源码进行了分析,相信大家对 HandlerThread 有了一定的认识。如果我们需要执行一个异步任务,并且执行完毕之后在主线程中更新 UI 的话,使用 HandlerThread 就不是很划算了。

但是如果采用 Handler + Thread 的写法来进行异步任务的话,要写很多代码,首先要在主线程中创建一个 Handler 对象,然后再创建一个子线程用来处理异步任务,然后在任务处理完的时候还要调用 主线程中的 Handler 对象去发送消息,主线程中的 Handler 对象接收到消息以后才能在主线程中更新 UI,这样做是很麻烦的。

不过 Android 给我们提供了一个更好的 Handler + Thread 的封装类 AsyncTask 来帮助我们更好的处理异步任务,然后更新 UI

接下来就来看下 AsyncTask 这个帮助类。

二、初识 AsyncTask

2.1 API 文档定义

老规矩,我们看下在 API 文档里面对 AsyncTask 的定义:

大概的意思是说:(以下翻译自 API 文档)

AsyncTask 能够让我们更加容易和合适的使用 UI 线程,这个类允许我们在后台执行一些操作并且发送结果到主线程,而不用写很多 ThreadHandler 的代码。
AsyncTask 被设计为一个关于 ThreadHandler 的帮助类,而不是提供一个通用的线程框架,AsyncTask 应该被用于短时间的操作,如果你需要让线程长时间的运行,那么非常推荐使用 java.util.concurrent包提供的多样的 API ,比如 ExexutorThreadPoolExecutorFutureTask来处理。
AsyncTask 定义在子线程中处理计算,然后再发送结果到 UI 线程,主要提供了三个常用类型的参数:ParamsProgressresult,并且有四个执行步骤:onPreExecutedoInBackgroundonProgressUpdateonPostExecute

所以我们可以知道 AsyncTask 可以解决主线程不能进行异步任务和子线程不能更新 UI 这个问题。

根据该类的定义

public abstract class AsyncTask<Params, Progress, Result> {}

可以看到 AsyncTask 是一个抽象类并且有三个泛型参数,

2.2 泛型参数

三个泛型参数分别是:

  • ParamsAsyncTask 执行任务所需要的参数类型
  • Progress 是在后台运行过程中,任务执行任务进度的参数类型
  • Result 是最终计算得到的结果的参数类型

需要注意的是:

如果AsyncTask确定不需要传递具体参数,那么这三个泛型参数可以用Void来代替。

2.3 必须实现的抽象方法

他提供的抽象方法是

protected abstract Result doInBackground(Params... params);

这个方法前面已经说了: doInBackground 方法是运行在子线程中处理异步任务的,我们使用 AsyncTask 本身就是为了在子线程中处理异步任务,所以必须重写该方法。

2.4 其他的重要的可重写的方法

另外,还有其他的一些重要的重写方法如下

  1. onPreExecute(任务执行之前调用该方法,运行在 UI 线程)
  2. doInBackground(任务执行的时候调用该方法,运行在子线程,主要进行耗时操作)
  3. onProgressUpdate (在 doInBackground 方法里面调用 publishProgress 方法不断的更新进度值,不断的调用该方法,运行在 UI 线程)
  4. onPostExecute(在 publishProgress 执行完以后把返回值传递给这个方法,在主线程中执行)

2.5 一些不需要重写的重要方法

  1. execute(Params... params) 用于开启 AsyncTask 的执行
  2. cancel(boolean mayInterruptIfRunning) 用于标记本次任务的状态我取消状态,并不是真正的去终止任务,而是把 mCancelled 设置为 true,所以我们还需要在 doInBackgroud 中根据 mCancelled 的值来做判断进而终止任务的执行,这个类似于我们要终止一个线程,如果调用 interrupt()方法 只是标记该线程中断,需要在线程内部进行标记判断来终止线程。

2.6 一些使用注意事项

  1. AsyncTask 的实例必须在 UI 线程创建
  2. execute(Params... params) 方法必须在 UI 线程调用
  3. 不要手动调用onPreExecute()、doInBackground(Params... params)、onProgressUpdate(Progress... values)、onPostExecute(Result result)这几个方法。
  4. doInBackground(Params... params)运行在子线程,不要写更新 UI 的操作
  5. 一个 AsyncTask 实例只能执行一次,如果第二次执行会报 java.lang.IllegalStateException: Cannot execute task :the task has already been executed (a task can be executed only once) 异常。
  6. 执行顺序为 onPreExecute() --> doInBackground() --> publishProgress() --> onProgressUpdate() --> onPostExecute()

三、AsyncTask 的使用

3.1 实例展示

新建 AsyncTaskActivity

public class AsyncTaskActivity extends AppCompatActivity {

    private static final String TAG = "AsyncTaskActivity";

    private Button mButton;
    private Button mCancel;
    private ProgressBar mProgressBar;
    private ImageView mImageView;

    private MyAsyncTask mAsyncTask;
    String mUrl = "https://image.uisdc.com/wp-content/uploads/2014/07/085625KMV.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        mButton = findViewById(R.id.download);
        mCancel = findViewById(R.id.cancel_download);
        mProgressBar = findViewById(R.id.progress);
        mImageView = findViewById(R.id.image);
        mAsyncTask = new MyAsyncTask();
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mAsyncTask.execute(mUrl);
            }
        });
        mCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //取消一个正在执行的任务,onCancelled方法将会被调用
                mAsyncTask.cancel(true);
//                mAsyncTask.onCancelled("取消了");
            }
        });
    }


    class MyAsyncTask extends AsyncTask<String, Integer, String> {

        private OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(15000, TimeUnit.MILLISECONDS)
                .readTimeout(15000, TimeUnit.MILLISECONDS)
                .writeTimeout(15000, TimeUnit.MILLISECONDS)
                .build();


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.d(TAG, "onPreExecute: 准备下载 运行在 UI 线程    ");
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            Log.d(TAG, "onPostExecute: 下载完成 运行在 UI 线程    ");
            Bitmap bitmap = BitmapFactory.decodeFile(s);
            mImageView.setImageBitmap(bitmap);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //Log.d(TAG, "onProgressUpdate: 下载进度 运行在 UI 线程    " + values[0]);
            mProgressBar.setProgress(values[0]);
        }

        /**
         * 后台下载图片,最终返回图片的本地地址
         * @param strings
         * @return
         */
        @Override
        protected String doInBackground(String... strings) {
            Log.d(TAG, "doInBackground: 后台开始下载 运行在子线程    " + strings[0]);
            Request request = new Request.Builder()
                    .url(strings[0])
                    .build();
            InputStream inputStream = null;
            FileOutputStream fileOutputStream = null;
            long downloadSize = 0;
            long totalSize;
            try {
                Response response = mOkHttpClient.newCall(request).execute();
                if (response.isSuccessful()) {
                    inputStream = response.body().byteStream();
                    totalSize = response.body().contentLength();
                    File file = new File(Environment.getExternalStorageDirectory(), "test1111.jpg");
                    fileOutputStream = new FileOutputStream(file);
                    byte[] buffer = new byte[512 * 1024];
                    int len;
                    while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
                        fileOutputStream.write(buffer, 0, len);
                        fileOutputStream.flush();
                        downloadSize += len;
                        float percent = (float) downloadSize / totalSize;
                        publishProgress((int) (percent * 100));
                    }
                    return file.getAbsolutePath();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (null != inputStream) {
                        inputStream.close();
                    }
                    if (null != fileOutputStream) {
                        fileOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onCancelled(String s) {
            super.onCancelled(s);
            Log.d(TAG, "onCancelled: " + s);
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            Log.d(TAG, "onCancelled: 下载取消");
        }
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <Button
        android:id="@+id/download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载" />

    <Button
        android:id="@+id/cancel_download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="取消下载" />

    <ProgressBar
        android:id="@+id/progress"
        style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/image"
        android:layout_width="320dp"
        android:layout_height="320dp"
        android:layout_gravity="center"
        android:layout_marginTop="24dp" />

</LinearLayout>

运行效果:

可以看到 AsyncTask 的使用是很简单的,比我们写 Thread 然后再写 Handler 简单了很多。

四、源码分析

上面讲解了 AsyncTask 的概念、方法、使用等,下面就仔细分析下,AsyncTask 到底是如何运行的。

4.1 先看看 AsyncTask 的成员变量

public abstract class AsyncTask<Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;
}

可以看到,上面定义的都是和线程池有关的,也就是说 AsyncTask 内部的线程是通过线程池来管理的。

public abstract class AsyncTask<Params, Progress, Result> {
    static {
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
            threadPoolExecutor.allowCoreThreadTimeOut(true);
            THREAD_POOL_EXECUTOR = threadPoolExecutor;
        }
}

在静态代码块中根据前面定义的常量初始化了线程池,并且赋值给本地的静态常量 THREAD_POOL_EXECUTOR。接着往下看:

public abstract class AsyncTask<Params, Progress, Result> {
    /**
     * An {@link Executor} that executes tasks one at a time in serial
     * order.  This serialization is global to a particular process.
     */
    // 这里又创建了一个线程池,主要是用于多个耗时任务的时候,使其按照顺序排列
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    // 接收最终结果的消息标示
    private static final int MESSAGE_POST_RESULT = 0x1;
    // 接收进度更新的消息标示
    private static final int MESSAGE_POST_PROGRESS = 0x2;
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    // AsyncTask 的静态内部类,继承于 Handler 用于从子线程接收到消息,然后切换到主线程
    private static InternalHandler sHandler;
    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;
    // 当前状态
    private volatile Status mStatus = Status.PENDING;
    // 是否取消
    private final AtomicBoolean mCancelled = new AtomicBoolean();
    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
    // 主线程的 Handler 
    private final Handler mHandler;
}

这里主要定义了一些关键的成员常量,来看几个主要的

4.1.1 SERIAL_EXECUTOR
 // 这里又创建了一个线程池,主要是用于多个耗时任务的时候,使其按照顺序排列
 public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

SerialExecutorAsyncTask 的一个内部类:

private static class SerialExecutor implements Executor {
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    Runnable mActive;
    public synchronized void execute(final Runnable r) {
        mTasks.offer(new Runnable() {
            public void run() {
                try {
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }
    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}

SerialExecutor 实现了 Executor 接口,内部维护了一个队列 ArrayDeque<Runnable> mTasks,以及一个成员变量 Runnable

execute 方法中,首先通过 mTasks.offer 方法把新建一个 Runnable 对象添加到队列尾部,然后再 run 方法里面去执行传递给 execute 方法的 Runnable 对象,

if (mActive == null) {
    scheduleNext();
}

如果当前的 mActive 是空的就去执行 scheduleNext()scheduleNext()方法里面其实就是通过 AyyayDequepool() 方法从任务队列 mTas``ks 中删除队列中的第一个元素,并把返回值赋值给 mActive,如果第一个元素不为空(也就是 mTasks 中有任务还未执行,就去调用 THREAD_POOL_EXECUTOR(真正的线程执行者)去执行这个任务。)如果执行 mTaskspool 方法返回的值为 null,那么什么都不做。

emmmmmmmmmmmmmmmmmmmmmmmmm

可能有点晕,简单再说下:
也就是说这个 SerialExecutor 存在的意义并不是用来具体的执行任务的,,它内部维护这一个队列,当调用他的 execute() 方法执行任务的时候,会先向其内部的队列 mTasks 尾部添加一个任务 (Runnable),然后判断其内部的 mActive 是不是有任务在执行,如果没有任务在执行,那么就从内部任务队列中取出一个任务去执行,直到任务执行完毕。

也就是说,SerialExecutor 对象,它只负责维护一个队列,让任务能够按照一定的顺序执行,真正执行任务的是在静态代码块中创建的线程池 THREAD_POOL_EXECUTOR。也就是说在 THREAD_POOL_EXECUTOR 这个线程池中,一次只能够执行到一个任务。

4.1.2 mCancelled 标记任务是否取消
4.1.3 mTaskInvoked 标记任务是否执行
4.1.4 mStatus 标记任务状态
4.1.5 sHandler 任务线程的 Handler
4.1.6 mHandler 主线程的 Handler

4.2 从入口看起 execute(Params... params)

我们先从运行任务的入口 execute 方法看起,源码如下:

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            case RUNNING:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task is already running.");
            case FINISHED:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                        + "(a task can be executed only once)");
        }
    }
    mStatus = Status.RUNNING;
    onPreExecute();
    mWorker.mParams = params;
    exec.execute(mFuture);
    return this;
}

可以看到首先会对 mStatus 进行判断,只要不是 PENDING(待执行) 状态的,都会抛出异常,而只要一个 AsyncTask 对象执行了 execute 方法,就会执行 mStatus = Status.RUNNING; 那么其状态就会被设置成 RUNNING,这也就解释了为什么一个 AsyncTask 对象只能被执行一次。

onPreExecute(); 

这段代码运行在主线程中,验证了前面说的 onPreExecute 方法是在异步任务执行前调用的,如果重写了 onPreExecute();就会在任务开始前进行调用。

mWorker.mParams = params; 这行代码是把我们传入的参数 赋值给 mWorker中的变量 mParams,我们先来看下 mWorker 是什么鬼?

private final WorkerRunnable<Params, Result> mWorker;

可以看到 mWorkerWorkerRunnable 的对象,

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    Params[] mParams;
}

WorkerRunnable 又是 AsyncTask 的静态内部抽象类,并且实现了 Callable 接口,并且内部存储了我们传入的参数。那么他是什么时候赋值的呢?继续往下看。

继续看下面一行:

exec.execute(mFuture);

exec 就是 AsyncTaskexecute 方法我们传进来的线程池。mFuture又是什么鬼?

mFutureFutureTask<V> 的对象, FutureTask<V> 实现了 RunnableFuture<V>接口,而RunnableFuture<V> 接口又继承于 RunnableFuture<V>,所有这里的 mFuture 可以实现在子线程中执行任务并且得到最终执行返回值的功能,继续往下看

我们创建 AsyncTask 对象时候,会调用其参构造方法:

public AsyncTask() {
    this((Looper) null);
}

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 *
 * @hide
 */
public AsyncTask(@Nullable Looper callbackLooper) {
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
        ? getMainHandler()
        : new Handler(callbackLooper);
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);
            Result result = null;
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                postResult(result);
            }
            return result;
        }
    };
    mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (ExecutionException e) {
                throw new RuntimeException("An error occurred while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e) {
                postResultIfNotInvoked(null);
            }
        }
    };
}

可以看到我们上面提到的 mWorkermFuture 都是在这里创建的。

先来看 mWorker

执行 mWorker 中的 call 方法的时候,代码已经处于子线程了,这时会把 mTaskInvoked 设置为 true,并且把参数传递给 doInBackground方法执行,所以说 doInBackground 是运行在子线程中的,我们可以做一些耗时任务。

最终会把 doInBackground 方法的到的返回值传递给 postResult 方法。

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    message.sendToTarget();
    return result;
}

postResult 方法中,通过 getHandler() 把完成的消息传递出去,看下: getHandler() 这个方法:

private Handler getHandler() {
    return mHandler;
}

mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
    ? getMainHandler()
    : new Handler(callbackLooper);

没错,这个Handler 就是通过主线程的 Looper 来创建的,是属于主线程的 Handler。也就是说,在主线程的 mHandler 接收到消息之后,以后的代码都是运行在主线程中了。

再来看下这个通过主线程 Handler 发送出的 Message 内容:

  • what 的值为 MESSAGE_POST_RESULT ,,这个是一个常量
  • obj 的值为 new AsyncTaskResult<Result>(this, result)

AsyncTaskResult :

@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
    final AsyncTask mTask;
    final Data[] mData;
    AsyncTaskResult(AsyncTask task, Data... data) {
        mTask = task;
        mData = data;
    }
}

AsyncTaskResult 对象里面存储了 AsyncTask 对象和最终的计算结果。

那么在哪里接收这个消息呢?

对的,直接搜索 MESSAGE_POST_RESULT 在哪使用的就行了,我找到了:

private static class InternalHandler extends Handler {
    public InternalHandler(Looper looper) {
        super(looper);
    }
    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
        switch (msg.what) {
            case MESSAGE_POST_RESULT:
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

就是这个 Internalhandler,它继承了 Handler,所以有处理消息的能力。

这里先拿到 Message.obj 的值赋值给 AsyncTaskResult<?> 的对象 result,然后把 result 对象中的 mData 传递给 mTask(也就是AsyncTask) 的 finish 方法;

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

这里先判断任务有没有取消掉,如果取消掉了,那么就调用 onCancelled(result);,不会调用 onPostExecute(result);反之亦然,这也说明了 onCancelled(result)onPostExecute(result); 肯定不会同时调用的。

最后再把当前任务的状态设置为完成 Status.FINISHED

与之类似的是,我们获取当前任务的进度值也是通过该种机制来进行的,有兴趣的可以去看下,这里就不多说了。

接下来看下 mFuture

mFuture = new FutureTask<Result>(mWorker) {
    @Override
    protected void done() {
        try {
            postResultIfNotInvoked(get());
        } catch (InterruptedException e) {
            android.util.Log.w(LOG_TAG, e);
        } catch (ExecutionException e) {
            throw new RuntimeException("An error occurred while executing doInBackground()",
                    e.getCause());
        } catch (CancellationException e) {
            postResultIfNotInvoked(null);
        }
    }
};

前面说了 mWorker 是实现了 Callable 接口的,在创建 mFuture 的构造参数中可以接收一个 Callable 类型的对象,这里会把 mWorker 传递进去,然后在执行 mFuture 的 do``ne 方法时调用 postResultIfNotInvoked(get()); 方法。

get() 表示获取 mWorkercall 的最终计算返回值,即最终的 Result

private void postResultIfNotInvoked(Result result) {
    final boolean wasTaskInvoked = mTaskInvoked.get();
    if (!wasTaskInvoked) {
        postResult(result);
    }
}

最终会根据 mTaskInvoked.get()来获取该任务是否执行,如果没被执行,那么就执行 postResult(result);

但是,我们前面在初始化 mWorker 的时候,会先执行了 mTaskInvoked.set(true);,所以,这里的 postResult(result); 正常情况下是执行不到的。

到这里大概已经清楚 mWorkermFuture 是干嘛的了?

但是需要注意的是,上面只是初始化了 mWorkermFuture,并没有去执行 mWorker 中的 call 方法和 mFuturedone 方法。

mWorker 中的 call 方法和 mFuturedone 方法什么时候执行呢?

调用 exec.execute(mFuture)了以后,就会去调用 mWorker 中的 call 方法,call 方法中会去调用 doInBackground 方法去执行异步任务,然后任务执行完毕以后,会调用 mFuturedone 方法,表示任务执行结束,然后就在 done 方法中调用 get() 方法获取执行结果传递给 postResultIfNotInvoked(get()) 了。

五、最后

至此,一次完整的异步任务执行流程就分析完毕了,相信你对 AsyncTask 应该有了更加清晰的认识了。
下篇文章我们来看下 IntentService 的相关代码。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值