Android开发笔记2:AsyncTask浅析

1、AsyncTask的构造方法

AsyncTask中最重要的四个方法:onPreExecute,doInBackground,onProgressUpdate,onPostExecute那么这四个方法是如何执行的,又是如何传递参数的呢?想知道AsyncTask类的内部工作方式,我们就必须了解AsyncTask的构造方法。

1)初始化WorkerRunnable对象mWorker,并实现了call()方法。

mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return doInBackground(mParams);
            }
        };
而WorkerRunnable类实现了Callable接口,并且有一个Params[] mParams成员变量

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }


2)初始化FutureTask对象mFuture,并实现了done()方法。这里实现的方式有些复杂,接下来会逐一解释

mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                Message message;
                Result result = null;

                try {
                    result = get();
                } 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) {
                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
                    message.sendToTarget();
                    return;
                } catch (Throwable t) {
                    throw new RuntimeException("An error occured while executing "
                            + "doInBackground()", t);
                }

                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                        new AsyncTaskResult<Result>(AsyncTask.this, result));
                message.sendToTarget();
            }
        };

第一、我们需要关心FutureTask类

我们注意到FutureTask类实现了RunnableFuture接口

public class FutureTask<V> implements RunnableFuture<V>

而实际上RunnableFuture接口只是分别继承了Runnable和Future接口,其中的run()方法就是Runnable中的run()方法。

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

第二、了解了Future类,接下来我们需要看看它的构造方法,看到这里我们发现实际上是用mWorker初始化FutureTask类的sync常量。

public class FutureTask<V> implements RunnableFuture<V> {
    private final Sync sync;
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);
    }

第三、需要了解Sync的构造方法,将mWorker传递给了Sync类的callable常量。

 private final Callable<V> callable;
 Sync(Callable<V> callable) {
            this.callable = callable;
        }

至此,构造方法部分已经介绍完了,那么接下来我们就来看看AsyncTask类是怎么工作的


2、AsyncTask的execute方法

1)执行onPreExecute()

这里我们就不用过多解释了,很明显第一步就执行了onPreExecute()方法。

public final AsyncTask<Params, Progress, Result> execute(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;
        sExecutor.execute(mFuture);

        return this;
    }

但我们需要注意的是,将传入的params参数赋值给了mWorker中的mParams,这一步实现了参数的传递。并且调用了sExecutor.execute(mFuture),而sExecutor就是ThreadPollExecutor,execute自然会执行mFuture的run方法了。

    private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);

2)执行doInBackground(Params... params)

执行mFuture的run方法后,我们很容易就看到了首先执行的就是callable.call()

public void run() {
        sync.innerRun();
    }

void innerRun() {
            if (!compareAndSetState(READY, RUNNING))
                return;

            runner = Thread.currentThread();
            if (getState() == RUNNING) { // recheck after setting thread
                V result;
                try {
                    result = callable.call();
                } catch (Throwable ex) {
                    setException(ex);
                    return;
                }
                set(result);
            } else {
                releaseShared(0); // cancel
            }
        }
在前面Sync的构造方法中,我们已经将mWorker赋值给了callable,所以自然会执行mWorker的call()方法了,这里重复贴下代码:

public Result call() throws Exception {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return doInBackground(mParams);
            }

从而实现了将execute(Params ... params)中的形参params传递给了mWorker,再传递给doInBackground方法,同时执行了该方法。


3)执行onPostExecute(Result result)

首先我们重贴下代码:

void innerRun() {
            if (!compareAndSetState(READY, RUNNING))
                return;

            runner = Thread.currentThread();
            if (getState() == RUNNING) { // recheck after setting thread
                V result;
                try {
                    result = callable.call();
                } catch (Throwable ex) {
                    setException(ex);
                    return;
                }
                set(result);
            } else {
                releaseShared(0); // cancel
            }
        }
其中得到了call()方法的返回结果result = callable.call() //实际上就是doInBackground的返回结果。

接着set(result),就是传递result的过程。实际上就是将得到的执行后的返回结果result赋值给了Sync类中的result对象,后面会通过Sync类中的get()方法再次得到该对象。

protected void set(V v) {
        sync.innerSet(v);
    }

void innerSet(V v) {
            for (;;) {
                int s = getState();
                if (s == RAN)
                    return;
                if (s == CANCELLED) {
                    // aggressively release to set runner to null,
                    // in case we are racing with a cancel request
                    // that will try to interrupt runner
                    releaseShared(0);
                    return;
                }
                if (compareAndSetState(s, RAN)) {
                    result = v;
                    releaseShared(0);
                    done();
                    return;
                }
            }
        }

最后,执行了FutureTask的done()方法。如下重贴代码:

protected void done() {
                Message message;
                Result result = null;

                try {
                    result = get();
                } 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) {
                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
                    message.sendToTarget();
                    return;
                } catch (Throwable t) {
                    throw new RuntimeException("An error occured while executing "
                            + "doInBackground()", t);
                }

                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                        new AsyncTaskResult<Result>(AsyncTask.this, result));
                message.sendToTarget();
            }

这里的Result result = get()实现了doInBackground返回值的传递。

public V get() throws InterruptedException, ExecutionException {
        return sync.innerGet();
    }

V innerGet() throws InterruptedException, ExecutionException {
            acquireSharedInterruptibly(0);
            if (getState() == CANCELLED)
                throw new CancellationException();
            if (exception != null)
                throw new ExecutionException(exception);
            return result;
        }

接下来在done()方法中调用了

message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(AsyncTask.this, result));
message.sendToTarget();

AsyncTaskResult就用来保存返回结果,并且通过发送消息的方式传递给对应的handler处理。

 private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }

从而实现了将result传递给onPostExecute(Result... result)的目的,同时调用了该方法

private static class InternalHandler extends Handler {
        @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;
                case MESSAGE_POST_CANCEL:
                    result.mTask.onCancelled();
                    break;
            }
        }
    }

最后,我们似乎忘记了onProgressUpdate(Progress... values)方法,不过没关系我本来就是要放在最后才讲的。

4)执行onProgressUpdate(Progress... values)

这个方法顾名思义就是为了在任务执行过程中更新状态信息,并且和其他几个方法不同的是由我们来决定是否更新,以及什么时候更新。通常我们会在doInBackground方法中显示的调用publishProgress来更新状态。

protected final void publishProgress(Progress... values) {
        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }

这样,通过发送消息的方式也交由对应的handler来处理,过程见3)中handleMessage方法。

至此我们就对AsyncTask类的实现方式有了一定的了解了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值