Android5.0 AsyncTask的实现分析

首先看一下AsyncTask在Android中的一个简单应用:

package com.example.zhy_asynctask_demo01;  

import android.app.Activity;  
import android.app.ProgressDialog;  
import android.os.AsyncTask;  
import android.os.Bundle;  
import android.util.Log;  
import android.widget.TextView;  

public class MainActivity extends Activity  
{  

    private static final String TAG = "MainActivity";  
    private ProgressDialog mDialog;  
    private TextView mTextView;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  

        mTextView = (TextView) findViewById(R.id.id_tv);  

        mDialog = new ProgressDialog(this);  
        mDialog.setMax(100);  
        mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
        mDialog.setCancelable(false);  

        new MyAsyncTask().execute();  

    }  

    private class MyAsyncTask extends AsyncTask<Void, Integer, Void>  
    {  

        @Override  
        protected void onPreExecute()  
        {  
            mDialog.show();  
            Log.e(TAG, Thread.currentThread().getName() + " onPreExecute ");  
        }  

        @Override  
        protected Void doInBackground(Void... params)  
        {  

            // 模拟数据的加载,耗时的任务  
            for (int i = 0; i < 100; i++)  
            {  
                try  
                {  
                    Thread.sleep(80);  
                } catch (InterruptedException e)  
                {  
                    e.printStackTrace();  
                }  
                publishProgress(i);  
            }  

            Log.e(TAG, Thread.currentThread().getName() + " doInBackground ");  
            return null;  
        }  

        @Override  
        protected void onProgressUpdate(Integer... values)  
        {  
            mDialog.setProgress(values[0]);  
            Log.e(TAG, Thread.currentThread().getName() + " onProgressUpdate ");  
        }  

        @Override  
        protected void onPostExecute(Void result)  
        {  
            // 进行数据加载完成后的UI操作  
            mDialog.dismiss();  
            mTextView.setText("LOAD DATA SUCCESS ");  
            Log.e(TAG, Thread.currentThread().getName() + " onPostExecute ");  
        }  
    }  
}  

在这个简单的Demo中我们可以看到 AsyncTask的入口在:

new MyAsyncTask().execute(); 

进入到源码中我们看下execute()方法:

    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

在函数中又调用了executeOnExecutor方法:

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

方法中根据一个枚举来判定AsyncTask的当前的状态:

    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:还未执行过executed
  • RUNNING:正在执行过程中
  • FINISHED:已经结束
    在executeOnExecutor中每个异步任务在完成前只能执行一次,通过上述的枚举类型中的状态实现,随后调用的是onPreExecute()方法:
    protected void onPreExecute() {
    }

这里还是在主线程中,我们可以重写这个方法,做一些开始异步操作前的一些准备动作。
执行完成后:

mWorker.mParams = params;

在Asytask中有两个重要的成员变量:

    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;

我们可以将这里的mWorker 视为一个Runable接口 这里将参数Parameter 传入到mWorker 中
接下来执行:

exec.execute(mFuture);

我们研究下这里的exec 变量:
它的传入参数是一个成员变量: sDefaultExecutor 来看下如何定义的:

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

最终先开始调用的excute方法就是执行这个内部类中的excute方法:
这个方法同时也是AsyTask的精髓:
在内部类中有一个成员变量:

final ArrayDeque<Runnable> mTasks

我们介绍下这个:
1)ArrayDeque有两个类属性,head和tail,两个指针。
2)ArrayDeque通过一个数组作为载体,其中的数组元素在add等方法执行时不移动,发生变化的只是head和tail指针,而且指针是循环变化,数组容量不限制。
3)offer方法和add方法都是通过其中的addLast方法实现,每添加一个元素,就把元素加到数组的尾部,此时,head指针没有变化,而tail指针加一,因为指针是循环加的,所以当tail追上head((this.tail = this.tail + 1 & this.elements.length - 1) == this.head)时,数组容量翻一倍,继续执行。
4)remove方法和poll方法都是通过其中的pollFirst方法实现,每移除一个元素,该元素所在位置变成null,此时,tail指针没有变化,而head指针加一,当数组中没有数据时,返回null。
5)因为ArrayDeque不是线程安全的,所以,用作堆栈时快于 Stack,在用作队列时快于 LinkedList。
其实说明白了它就是一个队列,里面的offer 方法就是将请求缓存起来,poll方法用来获取一个请求,我们知道在之前的版本中AsyTask被人诟病的就是当请求数超过128后 会抛出异常,但是在新版本的AsyTask中我们用队列将请求缓存后便不存在这种风险,实际上最终excute方法会调用到的方法是 mFuture中的run方法:

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

方法中我们可以看到最终是调用到的callable 的call方法这里的callable就是两个重要的成员变量的第二个:mWorker中的call:

            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }         

这里调用到了doInBackground(mParams) 进行耗时操作

其实总结起来AsyTask就是线程池和Handler的一个封装

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值