android AsyncTask 源码解读

来源:互联网 发布:如何设置网络共享权限 编辑:程序博客网 时间:2024/05/24 05:37

android AsyncTask 源码解读

AsyncTask是对Executor和Handler的组合包装类
AsyncTask是Android提供的轻量级的异步类,它使创建异步任务变得更加简单,不再需要编写任务线程和Handler实例即可完成相同的任务

AsyncTask执行过程:
1、AsyncTask启动、执行过程:execute(Params… params) => executeOnExecutor() => execute(Runnable runnable) => sDefaultExecutor.execute(runnable)
2、任务执行阶段:调用顺序doInBackground()=>publishProgress()=>onProgressUpdate(),阶段性结果
3、执行结束过程调用: 1、cancel() => onCancelled()(需在doInBackground()返回后) UI线程调用。 2、调用isCancelled(),检查执行状态

public abstract class AsyncTask<Params, Progress, Result> { //Params: 传递给异步任务执行时的参数的类型//Progress: 执行的进度返回给UI线程的参数的类型//Result: 异步任务执行完后返回给UI线程的结果的类型    private static final String LOG_TAG = "AsyncTask";    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // 获取CPU核数    private static final int CORE_POOL_SIZE = CPU_COUNT+ 1; // 核心线程数    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT*2 + 1; //线程池的最大线程数    private static final int KEEP_ALIVE = 1;    /*     //android     private static final int CORE_POOL_SIZE = 5;    private static final int MAXIMUM_POOL_SIZE = 128;    private static final int KEEP_ALIVE = 1;    */    private static final ThreadFactory sThreadFactory = new ThreadFactory() {        private final AtomicInteger mCount = new AtomicInteger(1); // 实例化原子整型类mCount,则mCount的方法是线程安全的        public Thread newThread(Runnable r) {            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());         }    };    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); //链表阻塞队列, 容量大小128    /**     * An {@link Executor} that can be used to execute tasks in parallel.     */    public static final Executor THREAD_POOL_EXECUTOR   // 异步线程池:多任务并发执行线程池         = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);     public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); // 同步线程池(串行线程池): 同一时间只能执行一个任务,串行执行任务,同步方法内调用THREAD_POOL_EXECUTOR.execute()达到最终串行执行任务    private static final int MESSAGE_POST_RESULT = 0x1;    private static final int MESSAGE_POST_PROGRESS = 0x2;    private static final InternalHandler sHandler = new InternalHandler(); // 静态内部类InternalHandler,其绑定了主线程的Looper和消息队列,完成消息的产生、发送、处理,    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; // 默认线程池为串行线程池    private final WorkerRunnable<Params, Result> mWorker;    private final FutureTask<Result> mFuture;    private volatile Status mStatus = Status.PENDING;    private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); //标识当前任务是否调用执行,原子布尔型变量(原子操作就是不能被线程调度机制中断的操作)    private static class SerialExecutor implements Executor {        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); // 数组双端队列,没有容量限制,其容量可自增长, mTasks的集合来保证任务的顺序执行        Runnable mActive;        public synchronized void execute(final Runnable r) { // 同步方法中维护双端队列,同时操作双端队列、调用并发线程池进行任务提交、执行            mTasks.offer(new Runnable() { //通过队列的offer方法将封装了final Runnable r的new Runnable对象添加到队尾                public void run() {                    try {                        r.run();  //执行r的run方法(最后在在线程池中执行),实现任务功能                    } finally {                        scheduleNext(); // 同步方法中调用并发线程池提交任务                    }                }            });            if (mActive == null) { //当前没有可执行任务,调用scheduleNext方法执行一个Runnable任务                scheduleNext();            }        }        protected synchronized void scheduleNext() {            if ((mActive = mTasks.poll()) != null) { //通过mTasks的poll方法出队操作,删除并返回队头的Runnable,并将返回的Runnable赋值给mActive,                THREAD_POOL_EXECUTOR.execute(mActive); // 调用THREAD_POOL_EXECUTOR的execute方法,提交mActive任务,并在线程池中执行mActive.run()方法            }        }    }    public enum Status {        //Indicates that the task has not been executed yet.        PENDING,        // Indicates that the task is running.        RUNNING,        //Indicates that {@link AsyncTask#onPostExecute} has finished.        FINISHED,    }    //异步任务的当前状态以及状态转变:PENDING=>RUNNING=>FINISHED    public static void init() {        sHandler.getLooper();    }    public static void setDefaultExecutor(Executor exec) {        sDefaultExecutor = exec;    }    /**     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.     */    public AsyncTask() {        mWorker = new WorkerRunnable<Params, Result>() { //实现了Callable接口的call方法            public Result call() throws Exception { //call方法是在线程池的线程中执行的,而不是在主线程中运行                mTaskInvoked.set(true); //将mTaskInvoked设置为true,表示任务开始执行                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // 将当前执行call方法的线程设置为后台线程                Result result = doInBackground(mParams); //在线程池的工作线程中执行doInBackground方法,执行实际的任务,并返回结果                Binder.flushPendingCommands();                return postResult(result);  //将执行完的结果传递给postResult方法            }        };        mFuture = new FutureTask<Result>(mWorker) {            @Override            protected void done() {                try {                    final Result result = get();                    postResultIfNotInvoked(result); // 任务正常执行完成                } 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); // 任务取消                } catch (Throwable t) {                    throw new RuntimeException("An error occured while executing "                            + "doInBackground()", t);                }            }        };    }    private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }    private Result postResult(Result result) {        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); // 发送“结果消息”        message.sendToTarget();        return result;    }    public final Status getStatus() {        return mStatus;    }    /**     * Override this method to perform a computation on a background thread. The     * specified parameters are the parameters passed to {@link #execute}     * by the caller of this task.     *     * This method can call {@link #publishProgress} to publish updates on the UI thread.     *     * @param params The parameters of the task.     *     * @return A result, defined by the subclass of this task.     */    protected abstract Result doInBackground(Params... params);    /**     * Runs on the UI thread before doInBackground()     */    protected void onPreExecute() {    }    /**     * Runs on the UI thread after doInBackground(). This method won't be invoked if the task was cancelled     * @param result: The result of the operation computed by #doInBackground     */    @SuppressWarnings({"UnusedDeclaration"})    protected void onPostExecute(Result result) {    }    /**     * Runs on the UI thread after publishProgress() is invoked.     * @param values The values indicating progress.     */    @SuppressWarnings({"UnusedDeclaration"})    protected void onProgressUpdate(Progress... values) {    }    @SuppressWarnings({"UnusedParameters"})    protected void onCancelled(Result result) {        onCancelled();    }        protected void onCancelled() {    }    /**     * Returns <tt>true</tt> if this task was cancelled before it completed     * normally. If you are calling {@link #cancel(boolean)} on the task,     * the value returned by this method should be checked periodically from     * {@link #doInBackground(Object[])} to end the task as soon as possible.     *     * @return <tt>true</tt> if task was cancelled before it completed     */    public final boolean isCancelled() {        return mFuture.isCancelled();    }    /**     * <p>Attempts to cancel execution of this task.  This attempt will     * fail if the task has already completed, already been cancelled,     * or could not be cancelled for some other reason. If successful,     * and this task has not started when <tt>cancel</tt> is called,     * this task should never run. If the task has already started,     * then the <tt>mayInterruptIfRunning</tt> parameter determines     * whether the thread executing this task should be interrupted in     * an attempt to stop the task.</p>     *     * @param mayInterruptIfRunning       * true:if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete.     * @return false: if the task could not be cancelled, typically because it has already completed normally; true:otherwise     *     * @see #isCancelled()     * @see #onCancelled(Object)     */    // 取消当前执行任务    public final boolean cancel(boolean mayInterruptIfRunning) {  //3、执行结束过程调用: cancel() => doInBackground()返回 => onCancelled() UI线程调用。 2、调用isCancelled(),检查执行状态        return mFuture.cancel(mayInterruptIfRunning);     }    public final Result get() throws InterruptedException, ExecutionException {        return mFuture.get();    }    /**     * Waits if necessary for at most the given time for the computation to complete, and then retrieves its result.     * @param timeout Time to wait before cancelling the operation.     * @param unit The time unit for the timeout.     * @return The computed result.     */    //等待计算完成,获取任务状态结果    public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {        return mFuture.get(timeout, unit);    }    /**     * Executes the task with the specified parameters. The task returns     * itself (this) so that the caller can keep a reference to it.     * This method must be invoked on the UI thread.     * @param params The parameters of the task.     * @return This instance of AsyncTask.     */    //传入参数,开始执行任务    public final AsyncTask<Params, Progress, Result> execute(Params... params) { // 1、AsyncTask启动、执行过程:execute(Params... params) => executeOnExecutor() => execute(Runnable runnable) => sDefaultExecutor.execute(runnable)        return executeOnExecutor(sDefaultExecutor, params);    }    /**     * Executes the task with the specified parameters. The task returns     * itself (this) so that the caller can keep a reference to it.     * This method must be invoked on the UI thread.     *     * @param exec The executor to use. #THREAD_POOL_EXECUTOR} is available as a convenient process-wide thread pool for tasks that are loosely coupled.     * @param params The parameters of the task.     *     * @return This instance of AsyncTask.     */    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 void execute(Runnable runnable) {        sDefaultExecutor.execute(runnable); //由默认线程池提交、执行任务    }    protected final void publishProgress(Progress... values) { // 2、任务执行阶段:调用顺序doInBackground()=>publishProgress()=>onProgressUpdate(),阶段性结果        if (!isCancelled()) {            sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();        }    }    private void finish(Result result) {        if (isCancelled()) {            onCancelled(result); // 任务被取消,执行onCancelled()方法        } else {            onPostExecute(result); //结果发传递给onPostExecute()方法, 可在UI线程中刷新结果        }        mStatus = Status.FINISHED; //AsyncTask的状态设置为完成状态    }    private static class InternalHandler extends Handler {        public InternalHandler() {                super(Looper.getMainLooper()); //Looper类的getMainLooper静态方法,该方法返回主线程的Looper,表示InternalHandler绑定了主线程        }        @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); // 可在UI线程中刷新显示执行进度                    break;            }        }    }    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {        Params[] mParams;    }    @SuppressWarnings({"RawUseOfParameterizedType"})    private static class AsyncTaskResult<Data> { // 封装AsyncTask与相关数据成AsyncTaskResult        final AsyncTask mTask;        final Data[] mData; //存储的数据        AsyncTaskResult(AsyncTask task, Data... data) { //data是可变数组            mTask = task;            mData = data;        }    }}

AsyncTask使用关键函数:
protected void onPreExecute(); // 当任务执行之前开始调用此方法,可以在这里显示进度对话框,属UI主线程。
protected abstract Result doInBackground(Params… params);//耗时操作,例如网络请求任务。由AsyncTask线程池中的线程调用执行异步任务
protected void onPostExecute(Result result);//处理doInBackground得到的数据,能够对UI进行操作,属UI主线程
protected void onProgressUpdate(Progress… values); //可以使用进度条增加用户体验度。 属UI主线程,用于显示任务执行的进度。
protected void onCancelled(Result result); //用户调用取消时,会调用此方法,属UI主线程

使用AsyncTask类,须遵守的准则:
Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法;
该task只能被执行一次,多次调用时将会出现异常;

示例:

public class MainActivity extends Activity{    private Button button;    private Button cancel;    private ImageView imageView;    private ProgressDialog progressDialog;    private final String IMAGE_PATH = "http://developer.android.com/images/home/kk-hero.jpg";    DownloadAsyncTask task;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = (ImageView)findViewById(R.id.imageView);        progressDialog = new ProgressDialog(MainActivity.this);        progressDialog.setTitle("Image Downloading");        progressDialog.setMessage("........Downloading......");        progressDialog.setCancelable(false);        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);           button = (Button)findViewById(R.id.button);           button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v){                task = new DownloadAsyncTask();                task.execute(IMAGE_PATH); //AsyncTask任务只能被执行一次,传入参数,开始执行异步任务                                                             //函数原型:public final AsyncTask<Params, Progress, Result> execute(Params... params)                cancel.setEnabled(true);            }        });        cancel = (Button) findViewById(R.id.cancel);          cancel.setOnClickListener(new View.OnClickListener() {              @Override              public void onClick(View v) {                           task.cancel(true);   //取消一个正在执行的任务            }          });        cancel.setEnabled(false);     }    public class DownloadAsyncTask extends AsyncTask<String, Integer, byte[]> //Params: String类型,指定的URL路径,进度参数Progress: Integer类型,返回值类型Result:byte[]类型    {        @Override        protected void onPreExecute(){ // UI 线程执行            super.onPreExecute();            progressDialog.show(); //ProgressDialog显示出来        }        @Override        protected byte[] doInBackground(String... params) // 异步线程(后台线程)中执行        {              ByteArrayOutputStream bos=new ByteArrayOutputStream();            byte[] imgBytes = new byte[]{};            try {               URL url=new URL(params[0]);               HttpURLConnection con=(HttpURLConnection)url.openConnection();               con.setConnectTimeout(5000);                 con.setReadTimeout(5000);                con.setDoInput(true);               con.connect();               InputStream is=con.getInputStream();               long maxSize=con.getContentLength(); //获取文件的大小               byte[] buffer=new byte[1024];               int len=-1;               long total_length=0;               while((len=is.read(buffer))!=-1){                   bos.write(buffer,0,len);                   bos.flush();                   total_length += len;                   int progress = ((int)(total_length/(float)maxSize) * 100);  // 得到当前图片下载的进度                   publishProgress(progress); //将当前进度更新给onProgressUpdate方法               }                         is.close(); //关闭输入流               con.disconnect(); //关闭连接               byte[] imgBytes=bos.toByteArray();           } catch (MalformedURLException e) {              e.printStackTrace();           } catch (IOException e) {              e.printStackTrace();           } catch (InterruptedException e) {              e.printStackTrace();           }           return imgBytes;        }        @Override        protected void onProgressUpdate(Integer... values){ // UI 线程执行            super.onProgressUpdate(values);              progressDialog.setProgress(values[0]); //更新ProgressDialog的进度条        }        @Override        protected void onPostExecute(byte[] result){ // UI 线程执行            super.onPostExecute(result);            Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);            imageView.setImageBitmap(bitmap);            progressDialog.dismiss();        }        @Override          protected void onCancelled() {   //取消执行中的任务时更改UI             progressDialog.setProgress(0);              cancel.setEnabled(false);          }     }}
原创粉丝点击