通过名字就可以知道,AsyncTask主要用于处理android中的异步任务。但是通过源码,我们可以看到它的实现其实还是依赖于Handler的异步消息处理机制。现在我们先来学习它的使用方式,然后再研究源码。
一.AsyncTask的基本用法:
AsyncTask是一个抽象类,在之类继承它时,必须指定三个泛型参数,这三个参数的用途如下:
1. 在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
2. 后台任何执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。3. 当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
自定义的AsyncTask之类如下示例:
public class DownAsyncTask extends AsyncTask<String, Integer, byte[]>
这里我们把AsyncTask的第一个泛型参数指定为String,表示在执行AsyncTask的时候需要传入String参数给后台任务。第二个泛型参数指定为Integer,表示使用整型数据来作为进度显示单位。第三个泛型参数指定为byte[],则表示使用一个byte数组来反馈执行结果。
当然,目前我们自定义的DownAsyncTask还是一个空任务,并不能进行任何实际的操作,我们还需要去重写AsyncTask中的几个方法才能完成对任务的定制。经常需要去重写的方法有以下四个:
onPreExecute()
这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
public class DownAsyncTask extends AsyncTask<String, Integer, byte[]>{ private String TAG = "DownAsyncTask"; private ProgressDialog mProgress; private Context mContext; private ImageView imageButton; public DownAsyncTask(Context mContext,ImageView imageButton){ this.mContext = mContext; this.imageButton = imageButton; } @Override protected byte[] doInBackground(String... params) { // TODO Auto-generated method stub android.util.Log.v(TAG,"DownAsyncTask--------doInBackground"); // 通过Apache的HttpClient来访问请求网络中的一张图片 HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(params[0]); byte[] image = new byte[]{}; try { HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); if(httpEntity != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { image = EntityUtils.toByteArray(httpEntity); } //..根据下载的情况,使用publishProgress()通知onProgressUpdate()更新进度条 } catch (Exception e) { e.printStackTrace(); } finally { httpClient.getConnectionManager().shutdown(); } return image; } @Override protected void onPreExecute() { // TODO Auto-generated method stub android.util.Log.v(TAG,"DownAsyncTask--------onPreExecute"); //设置并显示进度条 mProgress = new ProgressDialog(mContext); mProgress.setTitle("xiazai"); mProgress.setMessage("download is running"); mProgress.setProgressStyle(ProgressDialog.STYLE_SPINNER); mProgress.show(); super.onPreExecute(); } @Override protected void onPostExecute(byte[] result) { // TODO Auto-generated method stub //异步下载结束后,更换控件图片,关闭进度条 android.util.Log.v(TAG,"DownAsyncTask--------onPostExecute:"+result.length+" path:"+path); Bitmap mBitmap = BitmapFactory.decodeByteArray(result, 0, result.length); imageButton.setImageBitmap(mBitmap); mProgress.dismiss(); super.onPostExecute(result); } @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub android.util.Log.v(TAG,"DownAsyncTask--------onProgressUpdate"); super.onProgressUpdate(values); } @Override protected void onCancelled(byte[] result) { // TODO Auto-generated method stub android.util.Log.v(TAG,"DownAsyncTask--------onCancelled"); super.onCancelled(result); } @Override protected void onCancelled() { // TODO Auto-generated method stub android.util.Log.v(TAG,"DownAsyncTask--------onCancelled"); super.onCancelled(); } }
public class MainActivity extends Activity { private Button downButton; private ImageView mPictrue; private String uriPath = "http://ww2.sinaimg.cn/mw690/69c7e018jw1e6hd0vm3pej20fa0a674c.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); downButton = (Button) findViewById(R.id.button); mPictrue = (ImageView) findViewById(R.id.image); downButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub DownAsyncTask dat = new DownAsyncTask(MainActivity.this,mPictrue); dat.execute(uriPath); } }); } }
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); } }; 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 occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
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; }
public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; 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); } } }
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
private static class InternalHandler extends Handler { @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; } } }
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
protected final void publishProgress(Progress... values) { if (!isCancelled()) { sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } }