android AsyncTask 源码解读

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);  
        } 
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值