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则表示后台任务的返回结果的类型。
它有四个核心的方法:

  1. onPreExecute():在主线程中被调用,在异步任务执行之前被调用。
  2. doInBackground(Params params):在线程池中执行,用于执行异步任务,可以在这个方法中通过publishProgress更新任务进度。
  3. onProgressUpdate():在主线程中执行,当后台任务进度发生改变的时候被执行。
  4. 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()方法。

0 0
原创粉丝点击