android源码分析-AsyncTask

android源码分析-AsyncTask

我们一般创建一个AsyncTask的任务代码如下:

AsyncTask<String , String , String> task = new AsyncTask<String, String, String>() {

    @Overrideprotected void onPreExecute() {

        //UI线程,线程开始前执行,一般用于初始化操作super.onPreExecute();

    }


    @Overrideprotected String doInBackground(String... params) {

        //子线程后台线程执行操作return null;

    }


    @Overrideprotected void onProgressUpdate(String... values) {

        //UI线程,进度更新,通过在doInBackground方法中调用publishProgress传递过来更新进度super.onProgressUpdate(values);

    }


    @Overrideprotected void onPostExecute(String s) {

        //UI线程,后台操作执行完毕执行super.onPostExecute(s);

    }

};

task.execute();

下面开始分析源码:

流程先看AsyncTask的构造方法:
public AsyncTask() {

    mWorker = new WorkerRunnable<Params, Result>() {

        public Result call() throws Exception {

            mTaskInvoked.set(true);

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            //noinspection unchecked

            Result result = doInBackground(mParams);

            Binder.flushPendingCommands();

            return postResult(result);

        }

    };


    mFuture = new FutureTask<Result>(mWorker) {

        @Overrideprotected void done() {

            try {

                postResultIfNotInvoked(get());

            } catch (InterruptedException e) {

                android.util.Log.w(LOG_TAG, e);

            } catch (ExecutionException e) {

                throw new RuntimeException("An error occurred while executing doInBackground()",e.getCause());

            } catch (CancellationException e) {

                postResultIfNotInvoked(null);

            }

        }

    };

}

1.代码开始看可能有些难懂.其实说明一下就好很多了,WorkerRunnable是自定义的一个抽象类.里边先定义了进程的线程优先级(跟我们要讲的暂时没啥关系),又实现了doInBackground()方法,这就发现了doInBackground就是我们demo上new AsyncTask()必须重写的方法,AsyncTask中doInBackground()方法有注解@WorkerThread,说明他在工作线程.
2.然后return了postResult(result);,而且在new FutureTask中也调用了postResultIfNotInvoked(get());,而这个方法最后也是调用了postResult(result),所以来继续跟踪这个方法:

private Result postResult(Result result) {

    @SuppressWarnings("unchecked")

    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));

    message.sendToTarget();

    return result;

}

看到了熟悉的老朋友Message,然后有个方法message.sendToTarget();,这个是Message的方法,之前异步消息文档中有说过.
然后继续看getHandler(),这个不是Handler的方法,我们可以追踪这个方法”

private static Handler getHandler() {

    synchronized (AsyncTask.class) {

        if (sHandler == null) {

            sHandler = new InternalHandler();

        }

        return sHandler;

    }

}

看到了sHandler = new InternalHandler();说明重点代码就在InternalHandler()类:

private static class InternalHandler extends Handler {public InternalHandler() {

        super(Looper.getMainLooper());

    }


    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})

    @Overridepublic 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;

        }

    }

}

根据消息类型判断是否结束如果结束就走finish方法.
这里我们又看到了另一个熟悉的名字onProgressUpdate(),用来更新进度用的实现方法.如果没结束就走这个分支.
看一下上边说的finish方法:

private void finish(Result result) {

    if (isCancelled()) {

        onCancelled(result);

    } else {

        onPostExecute(result);

    }

    mStatus = Status.FINISHED;

}

这个就很好理解了,取消就调用取消的回调,结束就调用结束的回调.

我们还有个回调方法没找到,我们看一下:

@WorkerThreadprotected final void publishProgress(Progress... values) {

    if (!isCancelled()) {

        getHandler().obtainMessage(MESSAGE_POST_PROGRESS,new AsyncTaskResult<Progress>(this, values)).sendToTarget();

    }

}

这个调用应该是在doInBackground()方法中.通知onProgressUpdate()刷新进度.
看到了这里也是发出了一个Message.就应该在InternalHandler中的刷新进度的分支接受到消息.

下面看execute()方法:

通过跟踪发现调用了executeOnExecutor(sDefaultExecutor, params);:

@MainThreadpublic 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;

}

这里有个回调方法onPreExecute()就是在执行doInBackground()前在主线程执行的方法.

然后把参数赋给了mWorker.mParams,然后执行了exec.execute(mFuture);,这句就是让线程执行任务的关键代码.
这个类点不进去了,但是我们找到了另外一个execute(runnable)的方法,跟踪看一下有个sDefaultExecutor.execute(runnable);,
然后看一下sDefaultExecutor是什么鬼.继续找,找到了SERIAL_EXECUTOR,看看SERIAL_EXECUTOR是什么鬼吧.

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

        }

    }

}

这里有两个类executescheduleNext()方法,作用是把任务反倒队列中执行.
mTasks.offer方法是把任务放到队列末尾,THREAD_POOL_EXECUTOR.execute(mActive)应该是从头部取任务执行.
我觉得这的代码应该是新建ArrayDeque<Runnable> 线程队列,然后加了同步锁,执行了run开启线程,在结束的时候从线程池取出线程.
这样整个异步任务就执行完了.

总结

通过构造方法,实现了mWorker和mFuture(线程池类),先实现了doInBackground()告诉程序开启线程做什么,然后调用了postResult(),这个方法建立了Handler和Message系列,并且在Handler中接收结束和更新进度的msg.(现在有个问题mWorker中return的postResult()时机问题,为什么要在这里调用结束的方法?可能是mFuture里边做的,毕竟最后mWorker也是mFuture的参数,这里也请看到的大神们指导一下).
execute()方法在调用exec.execute(mFuture);前实现了onPreExecute()调用了线程开启的回调方法.接着新建ArrayDeque<Runnable> 线程队列,把mFuture任务添加到队尾,线程池从队列头取出任务执行.(可见Asynctask的任务是逐个完成的),这样异步任务就实现了.

有什么不对的地方,请大神们不吝赐教!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值