AsyncTask的使用&&理解
来源:互联网 发布:张大奕五家淘宝店 编辑:程序博客网 时间:2024/06/06 08:40
AsyncTask定义:他是一个轻量级的异步任务类,可以在线程池中执行后台任务,并且将任务的执行进度和结果传递给主线程,并在主线程中更新UI,由此可见,AsyncTask中封装了Handler和Thread,对与Handler的消息传递机制可以参考http://blog.csdn.net/actor1999/article/details/70210901
AsyncTask使用:
AsyncTask是一个抽象的泛型类,有三个泛型参数Params,Progress,Result,其中Params表示我们调用execute(Params params)传递的参数的类型,这个参数会传递到doInBackground(Params params),即我们执行后台任务需要的参数的类型。Progress表示用来表示后台任务的进度的参数的类型。Result则表示后台任务的返回结果的类型。
它有四个核心的方法:
- onPreExecute():在主线程中被调用,在异步任务执行之前被调用。
- doInBackground(Params params):在线程池中执行,用于执行异步任务,可以在这个方法中通过publishProgress更新任务进度。
- onProgressUpdate():在主线程中执行,当后台任务进度发生改变的时候被执行。
- onPostExecute():在主线程中执行,当后台任务执行完成后会被调用。
上述四个方法中,doInBackground()是抽象方法,所以我们继承AsyncTask的时候要重写这个方法。以下是一个不完整的实例,可以让我们大致了解以下AsyncTask的使用过程。
class MyAsyncTask extends AsyncTask<Uri, Integer, Cursor> { @Override protected void onPreExecute() { //在任务执行前做一些处理,比如弹出提示框 Toast.makeText(mContext, "开始获取数据", Toast.LENGTH_SHORT).show(); } @Override protected Cursor doInBackground(Uri[] uris) { Cursor cursor ; cursor = getContentResolver().query(uris[0], null, null, null, null); //可以在这里调用publishProgress()设置任务进度 return cursor; } @Override protected void onProgressUpdate(Integer... values) { //通过进度条来显示进度 progressBar.setProgress(values[0]); } @Override protected void onPostExecute(Cursor result) { //在这里做一些处理 } } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; MyAsyncTask myAsyncTask = new MyAsyncTask(); myAsyncTask.execute(uri); }
AsyncTask源码分析
我们从execute()方法开始分析
public final AsyncTask<Params, Progress, Result> execute(Params... params){ return executeOnExecutor(sDefaultExecutor, params); }
这里sDefaultExecutor是一个静态的成员变量
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;public static final Executor SERIAL_EXECUTOR = new SerialExecutor();//SerialExecutor实现了Executorprivate static class SerialExecutor implements Executor { //实例化一个队列,用来给Runnable排队 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); //当前正在运行的Runnable,没有就为null Runnable mActive; public synchronized void execute(final Runnable r) { //将Runnable入队 mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); //如果当前没有Runnable在运行,就执行scheduleNext() if (mActive == null) { scheduleNext(); } } //从队列出队一个Runnable,然后让一个线程调度器去执行 protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } }
可以看到,SerialExecutor(顺序调度器)只是一个用来将Callable排队的调度器,是并行真正执行线程任务的是THREAD_POOL_EXECUTOR。
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; }
可以看到,这里只要设置了状态,然后调用了onPreExecute();
将参数设置给mWorker.mParams;
最后调用我们上面分析的SerialExecutor的execute方法。
这里有两个变量我们需要搞清楚,分别是mWorker,mFuture,mWorker的类型是WorkerRunnable,mFuture是FutureTask,他们是在AsyncTask的构造函数里面初始化的。
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { //一个标识位,为true表示该task已经被调用过 mTaskInvoked.set(true); //设置线程优先级 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked Result result = doInBackground(mParams); Binder.flushPendingCommands(); return postResult(result); } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { //get()获取线程执行的结果 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); } } }; }
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams;}
我们先来分析以下WorkerRunnable,他是一个抽象类,实现了Callable方法,并且增加了一个Params的成员变量,可以理解为一个带参数的Callable,他的call方法如上面的代码所示,会调用doInBackground()方法,获取result,然后调用postResult(result),具体代码如下:
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
可以看到,这个方法主要是给Handler发送Message,我们可以看Handler是怎么处理的。
private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @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; } } }
可以看到,这是一个static的Handler,为了那够将环境切换到主线程,我们就必须在主线程创建Handler,由于Hanlder是static的,静态成员是在加载类的时候进行初始化,所以就要求我们AsyncTask必须在主线程中加载。
它主要是执行这个语句result.mTask.finish(result.mData[0]);
result的类型是AsycnTaskResult他持有一个AsycnTask引用,也就是说,这里调用的是Async的finish()方法,如下
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
这个方法主要做两件事,设置状态,还有,判断是否取消,取消就调用onCancelled,正常执行完毕,调用onPostExecute。
分析完WorkerRunnable,我们还要看以下FutureTask,这里的FutrueTask重写了done()方法,该方法不管任务是否正常执行,这个方法的主要逻辑就是调用postResultIfNotInvoked,先试图调用FutrurTask.get()方法尝试取回WorkerRunnable的执行结果,如果没有正常执行完毕,就调用postResultIfNotInvoked(null),post一个null的Result。postResultIfNotInvoked代码如下:
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } }
如果wasTaskInvoked标识为false(这个标识在WorkerRunnable的call方法执行的时候会置为true)就postResult(result);
至此,我们可以做一个总结:
首先,我们调用AsyncTask.execute(Params params)(必须在主线程中调用)的时候会调用executeOnExecutor(),在这个方法中,先调用onPreExecute(),然后用SerialExecutor将WorkerRunnable进行排队,用THREAD_POOL_EXECUTOR来执行,完成WorkerRunnable中的call方法,如果正常完成则postResult(Result),如果取消,postResult(null),postResult方法会sendMessage给Hanlder,Hanlder调用onPostExecute()方法。
- AsyncTask的使用&&理解
- AsyncTask的理解和使用
- 理解Android的AsyncTask
- Android AsyncTask的理解
- AsyncTask源码的理解
- 关于AsyncTask的理解
- AsyncTask的理解
- android AsyncTask的参数理解
- android AsyncTask的参数理解
- AsyncTask的理解(一)
- AsyncTask的使用方法和理解
- android AsyncTask的参数理解
- AsyncTask的使用方法和理解
- AsyncTask的使用方法和理解
- AsyncTask的使用方法和理解
- AsyncTask的使用方法和理解
- 我所理解的AsyncTask
- 理解AsyncTask的工作原理
- Android设置无标题或者全屏
- The user specified as a definer ('root'@'%') does not exist
- Shell脚本
- android 自定义相机Camera
- 数据降维方法总结
- AsyncTask的使用&&理解
- MySQL
- 上机三
- cent7配置nginx(一),nginx基础安装
- hibernate的事务配置详解和出现的问题
- 51单片机一种精确的判断脉冲宽度的方法
- jQuery事件绑定原理(1)
- mvc:interceptors拦截器配置
- HDU5643【约瑟夫环变形】