Android AsyncTask類
阿新 • • 發佈:2018-11-11
相關文章
Android AsyncTask類
Android Handler類
1. AsyncTask類
AsyncTask,非同步任務,用於在後臺執行緒執行一個任務,在UI執行緒上修改介面。AsyncTask<Params, Progress, Result>
需要確認三個泛型型別,如果型別不被使用,使用Void型別。
- Params,啟動任務執行的輸入引數
- Progress,後臺任務執行的百分比
- Result,後臺執行結果
例如需要下載一個圖片並顯示在ImageView上
,指定Params
為圖片地址,Progress
以數值代替,Result
Bitmap
物件。
private class BitmapAsyncTask extends AsyncTask<String, Integer, Bitmap> { @Override protected Bitmap doInBackground(String... strings) { try { URL uri = new URL(url); URLConnection connection = uri.openConnection(); InputStream input = connection.getInputStream(); int size = connection.getContentLength(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length, sum = 0; while ((length = input.read(buffer)) != -1) { outputStream.write(buffer, 0, length); sum += length; publishProgress(sum * 100 / size); } input.close(); return BitmapFactory.decodeByteArray(outputStream.toByteArray(), 0, outputStream.size()); } catch (IOException e) { } return null; } @Override protected void onProgressUpdate(Integer... values) { mPb.setProgress(values[0]); } @Override protected void onPostExecute(Bitmap bitmap) { mIvBitmap.setImageBitmap(bitmap); } }
BitmapAsyncTask繼承AsyncTask類,且至少覆蓋doInBackground
方法
- onPreExecute(),在UI執行緒上呼叫,在執行後臺執行緒前呼叫
- doInBackground(Params… params),在後臺執行工作執行緒
- onProgressUpdate(Progress… values),呼叫publishProgress方法修改進度
- publishProgress(Progress… values),在UI執行緒呼叫該方法改變進度
- onPostExecute(Result result),工作執行緒執行完畢,在UI執行緒上修改介面
呼叫execute方法下載
new BitmapAsyncTask().execute(url);
效果如下
2. AsyncTask類解析
AsyncTask構造方法,分別定義了mHandler
、mWorker
和mFuture
。
public AsyncTask() {
this((Looper) null);
}
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);
}
}
};
}
mHandler
是一個Handler
類,處理MESSAGE_POST_RESULT
和MESSAGE_POST_PROGRESS
兩個事件,在主執行緒中呼叫AsyncTask的finish
和onProgressUpdate
方法。
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
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;
}
}
}
執行AsyncTask的execute
方法,會先呼叫onPreExecute
方法,配置mWorker
的mParams
屬性,最後呼叫Executor
的execute
方法,mFuture
會呼叫mWork
的call
方法和自身的done
方法。call
方法呼叫doInBackground
,而done
方法呼叫postResult
。
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
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;
}
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
AsyncTask的publishProgress
方法,在UI執行緒裡修改進度。
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
3. 總結
AsyncTask
必須在UI執行緒中被呼叫。doInBackground
方法會被自動呼叫,並在後臺執行緒中執行。onPreExecute
、onPostExecute
和onProgressUpdate
會在UI執行緒中被呼叫。doInBackground
的返回值會傳給onPostExecute
。