Android总结03_AsyncTask解析

来源:互联网 发布:centos 拼音不出中文 编辑:程序博客网 时间:2024/06/07 00:48

一.简介

AsyncTask作为一个异步操作类,其主要作用是将耗时操作放入子线程中,再将返回的结果传递到UI线程中.

二.方法

AysncTask作为一个抽象类,使用时必须使用继承AsyncTask的类.为了保证能够和UI线程进行交互,其提供了几个主要方法

onPreExecute():UI线程中,为耗时操作做准备工作

doInBackground():异步线程中,进行耗时操作

onPostExecute(Result result):UI线程中,获取参数为doInBackGround返回的值,实现耗时操作执行完的工作

onPublishProgress(Progress.. progress):UI线程中,参数为进度数值,主要作用是表明当前耗时操作进度

onCancel(),onCancel(Result  result):UI线程中,表明耗时操作被取消后的执行工作

三.源码分析

AsyncTask作为异步线程操作类,同时还可以通过其五个方法与UI线程进行交互,主要内部使用了线程池进行耗时操作,使用Handler与外部进行交互.

首先,先定义一个类:定义三个泛型,分别为传入数值,进度,以及结果

public abstract class MyAsyncTask<Params,Progress,Result> {  
}

然后定义execute()方法

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

public final MyAsyncTask<Params, Progress, Result> executeOnExecutor(Executor executor, Params... params) {

}

从这可以看出execute方法后仍需要执行executeOnExecutor()方法,只不过在其基础上多了一个Executor类型的参数,

但是会在executeOnExecutor()方法中执行什么内容呢,其实这里就是执行准备工作,然后开始耗时操作了,下面对executorOnExecutor()方法的代码进行补全

public final MyAsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
        if (this.mExecuteInvoked) {
            throw new IllegalArgumentException("已经有任务正在执行");
        } else {
            //设置任务已经开始执行,保证任务在执行过程中只能执行一次
            this.mExecuteInvoked = true;
            //执行任务的开始准备工作
            this.onPreExecutor();
            //设置执行线程的参数
            this.mWorker.params = params;
            //执行耗时操作
            exec.execute(mFuture);
            return this;
        }

}

到这里我们可以看到onPreExecute已经执行了,但是出现了几个未知的参数mExecuteInvoked,mWorkder和mFuture.

mExecuteInvoked的定义如下:

//volatile是用来实现多线程同步变量的,mExecuteInvoked用来标志当前任务是否正在执行

private volatile boolean mExecuteInvoked = false;

下面我们在来看看mWorker是什么

//定义一个实现了Callable接口的抽象类

//Callable和Runnable差不多,只是在以下三点会有所区别:

//1.定义方法名不同,Callable的方法是Call().Runable的方法是run()

//2.Callable可以返回数据,Runable不能够返回数值

//3.Callable本身可以抛出异常,Runnable不可以抛出异常

public abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    Params[] params;
}

//在这里会涉及到doInBackGround,由于返回结果仍在子线程中,所以需要通过postResutl方法进行传递

private final WorkerRunnable<Params, Result> mWorker = new WorkerRunnable<Params, Result>() {
        @Override
        public Result call() throws Exception {
            //设置任务开始执行
            MyAsyncTask.this.mTaskInvoked.set(true);
            //设置为后台线程
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //执行耗时操作
            return MyAsyncTask.this.postResult(MyAsyncTask.this.doInBackground(params));
        }

};

由于上一步是在子线程中完成,需要与ui线程进行交互,所以在这里出现了至关重要的Handler类型的对象sHandler.以及一个用来携带数据类型AsyncTaskResult的对象

private Result postResult(Result result){
        //初始化即将发送的消息
        Message message = sHandler.obtainMessage(1, new AsyncTaskResult(this, new Object[]{result}));
        //发送
        message.sendToTarget();
        return result;

}

先来看看AsyncTaskResult的定义

private static class AsyncTaskResult<Data>{
        //表示当前执行的异步任务
        private MyAsyncTask task;
        //携带的数据
        private Data[] mData;

        public AsyncTaskResult(MyAsyncTask task, Data[] mData) {
            this.task = task;
            this.mData = mData;
        }

}

然后再看Handler的定义

private static class InternalHandler extends Handler{
        public InternalHandler() {
            //获取主线程
            super(Looper.getMainLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what){
                case 1://完成
                    result.task.finish(result.mData[0]);
                    break;
                case 2://更新进度
                    result.task.onProgressUpdate(result.mData);
                    break;
            }
        }
}

此时通过以上我们就能够明白,此时是已经从doInBackground->onPostResult->通过Handler->执行finish->onPostExecute()


但是从上面的程序我们发现mWorkder根本没有执行到,那么这个就涉及我们executeOnExecutor里面的变量mFuture

//Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果

private FutureTask<Result> mFuture;

public MyAsyncTask() {
        this.mFuture = new FutureTask<Result>(this.mWorker) {
            @Override
            protected void done() {
                try {
                    MyAsyncTask.this.postResultIfNotInvoked(get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (CancellationException e) {//取消异常
                    MyAsyncTask.this.postResult(null);
                }
            }
        };

}

private void postResultIfNotInvoked(Result result) {
        boolean wasTaskInvoked = this.mTaskInvoked.get();
        if (!wasTaskInvoked) {//如果异步任务没有执行,则发送返回结果出去
            this.postResult(result);
        }
    }


//上面主要就是针对耗时操作在子线程中执行的时候完成,取消 时的操作

下面在来仔细看看mWorker是怎么执行的

上面的execute方法想executeOnExecutor()方法传入了一个Executor对象exec,然后执行exec.execute()方法

private Executor sDefaultExecutor = new MyExecutor();


public class MyExecutor implements Executor {

    //任务队列
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();

    //当前运行的线程
    Runnable mActive;

    @Override
    public void execute(final Runnable r) {

         //将线程放到队列结尾

        //下面这个方法明确的意思是,第一次执行时,mActive为空,然后寻找到队首的线程就行执行,这以后其就一直有值,而当第一个线程执行完才会执行完第二个线程,虽然是多线程,可是却是一个线程接着一个线程执行的

        mTasks.offer(new Runnable() {
            @Override
            public void run() {
                try {
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }

}


//以上我们看到每次执行execute方法时,是将其先放入队列结尾,然后执行了scheduleNext()方法

protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            mThreadPollExecutor.execute(mActive);
        }
}

这里面又出现了一个新的未知参数mThreadPollExecutor,其实就是一个线程池对象,下面就是对齐初始化

     //线程池维护线程的最小数量
    private static final int CORE_POOL_SIZE = 5;
    //线程池维护线程的最大数量
    private static final int MAXIMUM_POOL_SIZE = 255;
    //线程池维护线程所允许的时间
    private static final int ALIVE_TIME = 1;
    //线程池所使用的缓冲队列
    private BlockingQueue<Runnable> workQuene;
    //创建新线程的线程工厂
    private ThreadFactory mThreadFactory = new ThreadFactory() {

        //创建新线程个数
        private AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "MyAsyncTask#" + mCount.getAndIncrement());
        }
    };

    //线程池
    private ThreadPoolExecutor mThreadPollExecutor;

    public MyExecutor() {
        this(CORE_POOL_SIZE);
    }

    public MyExecutor(int poolSize) {
        this.workQuene = new LinkedBlockingDeque<>(10);
        mThreadPollExecutor = new ThreadPoolExecutor(poolSize, MAXIMUM_POOL_SIZE, ALIVE_TIME, TimeUnit.SECONDS, workQuene, mThreadFactory);
    }


现在再将取消线程的代码贴一下,这个通过取消操作,执行FutureTask的cancel操作,然后执行done方法,再执行postReusltIfNotVoked方法

//任务是否取消
private final AtomicBoolean mCanceled = new AtomicBoolean();

protected void onCancel() {
}

protected void onCancel(Result result) {
    this.onCancel();
}

public final boolean isCanceled() {
    return this.mCanceled.get();
}

public final void cancel(boolean mayInterruptRunnable) {
    this.mCanceled.set(mayInterruptRunnable);
    this.mFuture.cancel(mayInterruptRunnable);
}







1 0
原创粉丝点击