1. 程式人生 > >Android查缺補漏(線程篇)-- AsyncTask的使用及原理詳細分析

Android查缺補漏(線程篇)-- AsyncTask的使用及原理詳細分析

catch 返回 rri 理解 ams tee ive lean keyword

本文作者:CodingBlock 文章鏈接:http://www.cnblogs.com/codingblock/p/8515304.html

一、AsyncTask的使用

AsyncTask是一種輕量級的異步任務類,可以很方便的在線程池中執行異步任務,並且將進度和結果傳遞給主線程。其底層由Thread+handler實現。

AsyncTask是一個抽象的泛型類,其類的聲明如下:

public abstract class AsyncTask<Params, Progress, Result>

其中三個泛型參數代表的意義如下:

  • Parmas:參數類型
  • Progress:異步任務的執行進度類型
  • Result:異步任務執行完畢後返回結果的類型

在使用AsyncTask執行異步任務需要創建一個類,讓這個類繼承AsyncTask,並實現相關方法,具體形式如下,在下面代碼中實現了幾個重要的方法,每個方法代表的意義可以見註釋:

/**
 * Created by liuwei on 18/2/28.
 */
public class MyAsyncTask extends AsyncTask<String, Integer, String> {

    /**
     * 在異步任務執行之前調用
     * 執行在主線程中
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 執行異步任務
     * 執行在線程池中
     * @param params
     * @return
     */
    @Override
    protected String doInBackground(String... params) {
        return null;
    }

    /**
     * 當異步任務被取消時執行此方法,此時將不會再調用onPostExecute方法
     */
    @Override
    protected void onCancelled() {
        super.onCancelled();
    }

    /**
     * 當異步任務執行進度改變時執行此方法
     * 執行在主線程中
     * @param values
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    /**
     * 當異步任務執行完成後執行此方法
     * 執行在主線程中
     * @param s
     */
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }
}

要註意的是,需要在doInBackground方法中調用publishProgress()發送任務執行進度,onProgressUpdate才能被回調。

執行AsyncTask是需要在主線程中調用:

new MyAsyncTask().execute();

在使用AsyncTask時有一些限制我們要註意:

  • AsyncTask類必須在主線程中加載。這是因為在AsyncTask中存在這個一個靜態類型的Handler對象成員,在AsyncTask被加載時,該靜態類型的Handler對象就會被初始化,所以這就要求了首次訪問AsyncTask要發送在主線程中。這一點在Android 4.1及以上版本中已經被系統自動完成。

  • AsyncTask的對象必須在主線程中創建。
  • AsyncTask的execute必須在主線程中調用。
  • 不能直接調用onPreExecute()、doInBackground()、onProgressUpdate()、onPostExecute()方法。
  • 一個AsyncTask對象只能調用一次execute,即每個對象只能被執行一次,否則會出異常。

1、使用AsyncTask執行異步任務的小例子

接下類使用AsyncTask,借助循環模擬一個耗時任務的小例子,還是用上面的MyAsyncTask類,並在其相關方法上面添加一些輔助代碼,詳細代碼如下:

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

    private final static String TAG = MyAsyncTask.class.getSimpleName();

    private int taskSize = 10;

    /**
     * 在異步任務執行之前調用
     * 執行在主線程中
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.i(TAG, "onPreExecute: ");
    }

    /**
     * 執行異步任務
     * 執行在線程池中
     * @param params
     * @return
     */
    @Override
    protected String doInBackground(String... params) {
        Log.i(TAG, "doInBackground: ");
        int i;
        for (i = 0; i < taskSize; i++) {
            SystemClock.sleep(1000);
            int progress = (int)((i / (float)taskSize) * 100);
            publishProgress(progress);

            if (isCancelled()) {
                break;
            }
        }
        return "執行結果:" + (i / (float)taskSize) * 100 + "%";
    }

    /**
     * 當異步任務被取消時執行此方法,此時將不會再調用onPostExecute方法
     */
    @Override
    protected void onCancelled() {
        super.onCancelled();
        Log.i(TAG, "onCancelled: ");
    }

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

    /**
     * 當異步任務執行進度改變時執行此方法
     * 執行在主線程中
     * @param values
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        Log.i(TAG, "onProgressUpdate: 執行進度:" + values[0] + "%");
    }

    /**
     * 當異步任務執行完成後執行此方法
     * 執行在主線程中
     * @param s
     */
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.i(TAG, "onPostExecute: result=" + s);
    }
}

在Activity中調用new MyAsyncTask().execute();執行Log如下:

.../cn.codingblock.thread I/MyAsyncTask: onPreExecute: 
.../cn.codingblock.thread I/MyAsyncTask: doInBackground: 
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:0%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:10%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:20%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:30%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:40%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:50%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:60%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:70%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:80%
.../cn.codingblock.thread I/MyAsyncTask: onProgressUpdate: 執行進度:90%
.../cn.codingblock.thread I/MyAsyncTask: onPostExecute: result=執行結果:100.0%

2、多個AsyncTask對象在執行異步任務時,默認是串行執行的,也可以通過executeOnExecutor讓其並發執行。

  • 在Android 1.6之前,AsyncTask處理任務時是采用串行方式,Android 1.6時,AsyncTask處理任務時是在線程池中並行處理任務。但在Android 3.0開始,AsyncTask又開始采用串行方式處理任務。

我們稍加改造一下上面的示例,在構造方法中傳入一個taskId,然後在關鍵log中輸出這個taskId,以便於區分:

private int taskId;

public MyAsyncTask(int taskId) {
    this.taskId = taskId;
}

/**
 * 在異步任務執行之前調用
 * 執行在主線程中
 */
@Override
protected void onPreExecute() {
    super.onPreExecute();
    Log.i(TAG, "taskId= " + taskId + ": onPreExecute: ");
}

// 其他方法類比onPreExecute方法中的log增加taskId,就不貼出了

在Activity中初始化兩個AsyncTask對象,並調用excute執行任務:

public class AsyncTaskActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        MyAsyncTask task1 = new MyAsyncTask(1);
        MyAsyncTask task2 = new MyAsyncTask(2);
        task1.execute();
        task2.execute();
    }
}

log如下:

.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onPreExecute: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onPreExecute: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: doInBackground: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:0%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:10%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:20%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:30%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:40%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:50%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:60%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:70%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:80%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:90%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onPostExecute: result=taskId= 1: 執行結果:100.0%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: doInBackground: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:0%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:10%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:20%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:30%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:40%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:50%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:60%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:70%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:80%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:90%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onPostExecute: result=taskId= 2: 執行結果:100.0%

可以看到兩個任務是串行執行的。

  • 使用executeOnExecutor方法

AsyncTask

executorOnExecutor方法有兩個參數,第一個是Executor,第二個是任務參數。

第一個參數有兩種類型:

  • AsyncTask.SERIAL_EXECUTOR : 表示串行執行
  • AsyncTask.THREAD_POOL_EXECUTOR :表示並發執行

在執行task2時調用executeOnExecutor,觀察執行結果:

public class AsyncTaskActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        MyAsyncTask task1 = new MyAsyncTask(1);
        MyAsyncTask task2 = new MyAsyncTask(2);
        task1.execute();
        task2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
}

log如下:

.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onPreExecute: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onPreExecute: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: doInBackground: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: doInBackground: 
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:0%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:0%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:10%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:10%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:20%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:20%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:30%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:30%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:40%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:40%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:50%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:50%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:60%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:60%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:70%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:70%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:80%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:80%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onProgressUpdate: 執行進度:90%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 2: onPostExecute: result=taskId= 2: 執行結果:100.0%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onProgressUpdate: 執行進度:90%
.../cn.codingblock.thread I/MyAsyncTask: taskId= 1: onPostExecute: result=taskId= 1: 執行結果:100.0%

從log可以看到,兩個任務在並發執行。

二、AsyncTask的原理

  • 1、首先在AsyncTask被初始化時構建一個WorkerRunnable(mWorker)和一個FutureTask(mFuture),後面在執行的過程中會將封裝好的mFuture放入一個線程池中執行。
  • 2、在外界調用AsyncTask.execute方法之後,開始啟動AsyncTask任務,根據代碼查看調用過程如下:
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}
  • 3、在execute方法中又調用了executeOnExecutor方法:
@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;
}

我們需要了解的是,一個AsyncTask任務有三種狀態:PENDING(未開始)、RUNNING(運行中)、FINISHED(已完成)。
從上面源碼我們可以看到,一個AsyncTask實例任務只能運行一次,只有是在PENDING狀態下,任務才能正常運行,否則就會拋出異常。

接著在執行任務前先調用了onPreExecute方法,並將參數賦值給mWorker的參數數組,然後使用exec執行在AsyncTask初始化階段封裝好的mFuture。

  • 4、從第二步可以知道exec就是sDefaultExecutor,它是一個Executor對象,相關的源碼如下:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

/**
 * 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 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);
        }
    }
}

從源碼可以進一步看出,sDefaultExecutor是SerialExecutor對象,是一個串行的線程池,同一個進程中的所有的AsyncTask任務都在這個線程池中排隊執行。

SerialExecutor的execute方法首先會將FutureTask任務加入到mTasks隊列中,此時如果沒有正在活動的任務就會調用scheduleNext執行下一個AsyncTask任務。

  • 5、接下來我們再回過頭來看AsyncTask的構造器中在創建mWorker和mFuture時都做了些什麽:
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); 
            }
        }
    };
}
  • 6、先來分析一下上面源碼中的WorkerRunnable的call方法:

WorkerRunnable的call方法中的代碼很好理解,首先調用了mTaskInvoked.set(true),將任務的設為已調用狀態。接著調用了doInBackground方法並獲取了返回值,然後將返回值傳遞給postResult()方法,再看postResult方法的源碼如下:

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));// 在這裏將doInBackground的返回結果result封裝到AsyncTaskReuslt對象裏面通過handler發送給主線程
    message.sendToTarget();
    return result;
}

在此方法中通過handler發送了一條MESSAGE_POST_RESULT的消息。此handler的相關代碼如下(為方便查看,適當調整了代碼順序):

private final Handler mHandler;

private Handler getHandler() {
    return mHandler;
}

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 */
public AsyncTask() {
    this((Looper) null);  // 在這裏傳入了null
}

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 *
 * @hide
 */
public AsyncTask(@Nullable Handler handler) {
    this(handler != null ? handler.getLooper() : null); // 根據上一步調用可知,handler為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()                              // 根據上一步調用可知,callbackLooper為null,在此會調用getMainHandler()
        : new Handler(callbackLooper);
        ...
}

private static Handler getMainHandler() {
    synchronized (AsyncTask.class) {
        if (sHandler == null) {
            sHandler = new InternalHandler(Looper.getMainLooper());
        }
        return sHandler;
    }
}

private static InternalHandler sHandler;

在上面的源碼中可知,最終getHandler()方法最終是為sHandler,而sHandler是一個靜態的Handler對象,sHandler的作用是將執行環境切換到主線程中,所以這就要求sHandler要在主線程中被初始化,而由於靜態成員會在類加載時被初始化,這就又要求了AsyncTask類必須在主線程中加載,否則該進程中的AsyncTask任務都無法正常工作。InternalHandler相關的源碼如下:

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]); // 調用AsyncTask的finish方法。
                break;
            ...
        }
    }
}

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);     // 如果任務被取消了就去調用onCancelled方法。
    } else {
        onPostExecute(result);   // 任務完成後就將執行結果傳遞給onPostExecute方法
    }
    mStatus = Status.FINISHED;   // 最後將狀態置為FINISHED
}
  • 7、接著再來看一下第五步中的FutureTask的源碼
mFuture = new FutureTask<Result>(mWorker) {
    @Override
    protected void done() {     // 1、在執行完mWorker的call方法之後會執行done方法。2、或者在FutureTask任務被取消後也會執行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); // 在Future任務被取消時,在此段代碼中就會拋出CancellationException異常,即會執行此方法。
        }
    }
};

我們知道Future被執行後,會調用傳入的mWorker的call方法,在執行完mWorker的call方法之後或者FutureTask被取消時會調用done方法,我們看到源碼中在done方法中調用postResultIfNotInvoked():

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

在這個方法中可以看到,只有當wasTaskInvoked為false是才會發送結果,也就是說,這一步是在WorkerRunnable任務未被執行並取消的情況下才發送結果給主線程,在前幾步中我們就已經知道了postResult()方法中的調用過程,最終會調用到finish方法。

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);     // 如果任務被取消了就去調用onCancelled方法。
    } else {
        onPostExecute(result);   // 任務完成後就將執行結果傳遞給onPostExecute方法
    }
    mStatus = Status.FINISHED;   // 最後將狀態置為FINISHED
}

在任務被取消的情況下回調了onCancelled方法,至此AsyncTask異步任務執行流程基本分析完了。

三、小結

最後簡單總結一下AsyncTask的原理:

  • 在AsyncTask類中有兩個線程池(SerialExecutor、THREAD_POOL_EXECUTOR)和一個Handler(InternalHandler),其中SerialExecutor線程池用於對任務排隊,THREAD_POOL_EXECUTOR用於真正的執行任務,InternalHandler的作用是將執行環境切換到主線程中,而AsyncTask類中的InternalHandler變量是一個靜態類型的變量,這也就決定了AsyncTask類必須在主線程中加載。
  • 在調用AsyncTask的executor方法開始執行異步任務時,會首先調用onPreExecute方法通知外界任務已經開始,接著使用線程池執行前面FutureTask任務。
  • 前面所說的這個FutureTask任務是在AsyncTask初始化時被封裝好的,在該任務中調用了doInBackground方法用於異步執行我們添加的耗時任務,doInBackground方法執行完畢會通過InternalHandler將返回結果發送到onPostExecute中,該方法是運行在主線程中。

  • 《Android開發藝術探索》

源碼地址:本系列文章所對應的全部源碼已同步至github,感興趣的同學可以下載查看,結合代碼看文章會更好。源碼傳送門

本文作者:CodingBlock 文章鏈接:http://www.cnblogs.com/codingblock/p/8515304.html

Android查缺補漏(線程篇)-- AsyncTask的使用及原理詳細分析