Android 18章:ASYNCTASK分析一波
4956 ワード
私たちは初心者のAndroidでAsyncTaskを使ったことがあります.ネットワークにUIコントロールの変更を要求するのに便利なクラスです.面接官が少なくてもAsyncTaskの内容を聞くことが多いので、このような内部の論理を分析してみましょう.
AsyncTaskの説明
AsyncTask内部にはHandlerとThreadがカプセル化されており,uiスレッドを元に変更し,サブスレッドで時間のかかる操作を行う.同時にAsyncTaskは抽象的な汎用クラスである Paramsはパラメータタイプ(doInBackgroundのパラメータ)を表し、通常は要求url である. Progressは進捗タイプ(onProgressUpdateのパラメータ)を表し、通常Integer です. Resultは結果の戻りタイプ(onPostExecuteのパラメータ)を表し、asynctaskがパラメータを渡す必要がない場合、上記3つのパラメータタイプ の代わりにVoidを使用する.
AsyncTaskの4つのコアメソッド onPreExecute()非同期開始前にこのメソッドが実行され、dialog が表示されます. doInBackground(Params...params)オンライン・スレッド・プールで実行される非同期タスク.このメソッドではpublishProgress入力int進捗値を呼び出して進捗を更新し、結果をonPostExecuteに返します.ここで省略記号は複数の同じタイプのパラメータを入力できることです. onPorgressUpdate(Progress...progress)このメソッドはメインスレッドで実行され、タスクの進捗状況が変更されると、ダウンロードの進捗状況 を表示するなど、このメソッドが呼び出されます. onPostExecute(Result...result)プライマリスレッドが実行しますが、非同期メソッドが実行されると呼び出されるメソッドです.入力パラメータはdoInBackgroundの戻り値である.
ps:doInBackgroundのスレッドがキャンセルされるとonCancelledというメソッドにコールバックし、このメソッドがonPostExecuteを呼び出されると呼び出されません.
まとめ: asynctaskオブジェクトをプライマリスレッドで作成し、executeメソッド を呼び出します. doinbackgroundメソッド を直接呼び出すことはできません. asynctaskオブジェクトは1回のみ を実行します. 3.0までasynctaskはパラレルスレッドプールで実行し、3.0以降asynctaskはシリアルスレッドプールに変更します.もちろんasynctaskで実行できます.executeOnExecutorは、タスク を並列に実行する
ソースエントリexecute
AsyncTaskが実行を開始する方法はnew AsyncTask()である.execute(url 1)、executeはまたexecuteOnExetutorメソッドを呼び出してシリアルのスレッドプールSDefaultExecutorとurlパラメータを入力します.次のコード:
上のsDefaultExecuteはnewのSerialExecuteクラスです
SerialExecutorクラスに入ると、このクラスにはmTaskの中のRunnableが並んで実行されているのが見えます.そして、実行完了と判断して次のタスクの実行を開始する.
次に、executeOnExetutorに戻ると、現在のタスクのステータスを記録するmStatusが表示され、ステータスが変更されます.
各AsyncTaskはonPreExecuteメソッドを最初に実行し、スレッドプールexec.execute(mFuture);実行を開始します.ここのmFutureはRunnableです
次にmFutureをSerialExecuterに転送するexecuteメソッドを実行し、前のmFutureオブジェクトをキューmTaskに挿入し、現在タスクが行われているかどうかを判断し、アクティブでない場合はschedulNextメソッドを呼び出して次のasynctaskタスクを実行します.
Asynctaskには2つのスレッドプール(キューに並ぶためのserialexecutorと本当にタスクを実行するためのTHREAD_POOL_EXECUTOR)と(スレッドスケジューリングを担当する)internalHandlerがあります
その後Asynctaskの構築方法mWorkでcallメソッドを呼び出しmTaskInvokedをtrueに設定しdoinbackgroundを呼び出して戻り値を得てonpostexecuteメソッドを呼び出し、
postResultメソッドでは、finish taskを実行するためにmessageをsHandleに送信するか、進捗バーを更新するか、ここでfinishはonCancelledとonPostexecuteを呼び出す2つのケースがある.
AsyncTaskの説明
AsyncTask内部にはHandlerとThreadがカプセル化されており,uiスレッドを元に変更し,サブスレッドで時間のかかる操作を行う.同時にAsyncTaskは抽象的な汎用クラスである
public abstract class AsyncTask{}
AsyncTaskの4つのコアメソッド
ps:doInBackgroundのスレッドがキャンセルされるとonCancelledというメソッドにコールバックし、このメソッドがonPostExecuteを呼び出されると呼び出されません.
まとめ:
ソースエントリexecute
AsyncTaskが実行を開始する方法はnew AsyncTask()である.execute(url 1)、executeはまたexecuteOnExetutorメソッドを呼び出してシリアルのスレッドプールSDefaultExecutorとurlパラメータを入力します.次のコード:
@MainThread
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
上のsDefaultExecuteはnewのSerialExecuteクラスです
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
SerialExecutorクラスに入ると、このクラスにはmTaskの中のRunnableが並んで実行されているのが見えます.そして、実行完了と判断して次のタスクの実行を開始する.
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
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);
}
}
}
次に、executeOnExetutorに戻ると、現在のタスクのステータスを記録するmStatusが表示され、ステータスが変更されます.
各AsyncTaskはonPreExecuteメソッドを最初に実行し、スレッドプールexec.execute(mFuture);実行を開始します.ここのmFutureはRunnableです
@MainThread
public final AsyncTask 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;
}
次にmFutureをSerialExecuterに転送するexecuteメソッドを実行し、前のmFutureオブジェクトをキューmTaskに挿入し、現在タスクが行われているかどうかを判断し、アクティブでない場合はschedulNextメソッドを呼び出して次のasynctaskタスクを実行します.
Asynctaskには2つのスレッドプール(キューに並ぶためのserialexecutorと本当にタスクを実行するためのTHREAD_POOL_EXECUTOR)と(スレッドスケジューリングを担当する)internalHandlerがあります
その後Asynctaskの構築方法mWorkでcallメソッドを呼び出しmTaskInvokedをtrueに設定しdoinbackgroundを呼び出して戻り値を得てonpostexecuteメソッドを呼び出し、
postResultメソッドでは、finish taskを実行するためにmessageをsHandleに送信するか、進捗バーを更新するか、ここでfinishはonCancelledとonPostexecuteを呼び出す2つのケースがある.
public AsyncTask() {
mWorker = new WorkerRunnable() {
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;
}
};