码迷,mamicode.com
首页 > 移动开发 > 详细

Android:AsyncTask源码解析

时间:2015-07-10 09:37:54      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:asynctask   源码   

简单实例

这里直接拿以前写过的一个小Demo,根据这个Demo来分析源码。

public class MainActivity extends ActionBarActivity {  
    ...
    Private MyAsyncTask asyncTask;  
    protected void onCreate(Bundle savedInstanceState) {  
        ... 
        asyncTask = new MyAsyncTask();  
        // 点击button进行异步任务
        button.setOnClickListener(new OnClickListener() {  
        ...
                asyncTask.execute("Leelit"); // 这个参数就是传入参数,常用于URL网络下载,可以为空。  
            }  
        });  

    }  

    /* 泛型类AsyncTask有三个参数:Params,传入参数;Progress,进度;Result,返回结果。也可以使用Void表示该参数为空。*/ 
    private class MyAsyncTask extends AsyncTask<String, Void, String> {  

        @Override  
        protected String doInBackground(String... string) {  
            // TODO Auto-generated method stub  
            String conutString = string[0]; // 字符串可变参数
            int z = 0;  
            // 进行5亿次计算,模拟一个耗时任务  
            for (int i = 0; i < 1000000; i++) {   
                for (int j = 0; j < 500; j++) {  
                    z++;  
                }  
            }  
            conutString += " has executed ++ computation for " + z + " times";                                                         
            Log.e("ProcessInfo", "the task is done");   
            return conutString; // 将计算结果返回,传给onPostExecute()  
        }  

        @Override  
        protected void onPostExecute(String result) {  
            // TODO Auto-generated method stub  
            super.onPostExecute(result);   
            textView.setText(result); // 刷新UI  
        }  
    }  

}  

流程

  • 第一步:实例化MyAsyncTask,进入AsyncTask构造函数
public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

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

        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(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) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

可以看到,AsyncTask的构造函数主要是实例化了mWorkermFuture两个对象,看下这两个对象所属类。

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

WorkerRunnable是个抽象类,实现了Callable接口,需要在子类里面重写call方法,并且里面有参数字段。而这个抽象方法返回postResult(doInBackground(mParams)),postResult方法返回一个result,并且内部通过Handler将结果发送给主线程。而mFuture这个对象可以看作是对mWorker对象的包装。

private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

  • 第二步:执行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;
    }

传入的参数分别为sDefaultExecutorparams,由此方法可知,任务是只会被执行一次的,否则抛出异常。
executeOnExecutor方法进行:

  1. mStatus = Status.RUNNING,设置任务的状态
  2. onPreExecute(),调用这个可能重写的方法,这也是用户感知的第一步
  3. mWorker.mParams = params,设置任务的参数
  4. exec.execute(mFuture),执行这个任务,上面也说了可以把mFuture当成是mWorker的封装。

接下来看下最后的exec.execute(mFuture)方法,注意这个execute是指sDefaultExecutorexecute方法了,这里易与AsyncTask的execute方法混淆。

public static void execute(Runnable runnable) {
        sDefaultExecutor.execute(runnable);
    }

重点看下sDefaultExecutor这个类

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();    

sDefaultExecutor是一个SerialExecutor对象,接着看SerialExecutor类。

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

一步一步走下来,最后的execute方法就是通过一个任务队列和一个线程池来执行任务,这个线程池在不同版本参数也所有不同。

    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

最后我们来看下Handler是怎样处理message的

private static class InternalHandler extends Handler {
        public InternalHandler() {
            super(Looper.getMainLooper());
        }

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

可以看到有两个状态,MESSAGE_POST_RESULT代表任务完成,此时调用finish方法,这个方法内部的主要逻辑就是调用onPostExecute()方法,而MESSAGE_POST_RESULT就代表进度,此时调用的则是onProgressUpdate方法。
很明显,当我们在重写的doInBackground方法调用publishProgress时,handler就会发送包含MESSAGE_POST_PROGRESS状态的message。

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

小结

  1. 实例化AsyncTask对象,构造方法里面实例化mWorker对象和mFuture对象,mWorker对象是一个实现Callable接口的对象,call方法调用postResult(doInBackground(mParams),postResult方法则是通过handler发送消息给主线程,最后再用一个mFuture对象封装mWorker对象。
  2. 执行AsyncTask.execute(params)方法
    1. 执行executeOnExecutor(sDefaultExecutor, params);
    2. 执行onPreExecute方法,设置mWorker参数,调用sDefaultExecutor.execute(mFuture);
    3. THREAD_POOL_EXECUTOR.execute(mActive),用一个线程池,串行执行任务。

执行流程:

  1. myAsyncTask.execute(parmas …);
  2. onPreExecute(),设置mWorker/mFuture参数;
  3. sDefaultExecutor.execute(mFuture),内部是一个串行执行任务的线程池,而任务就是在第2步重写的doInBackground方法;
  4. 执行任务postResult(doInBackground(params))/publishProgress(Progress… values),通过handler发送消息给主线程。

在3.0版本之前任务是可以并发执行的,3.0后就串行了,如果我们需要在3.0版本之后并发执行任务,则可以调用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params),而不用内部维护一个串行任务队列的sDefaultExecutor。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android:AsyncTask源码解析

标签:asynctask   源码   

原文地址:http://blog.csdn.net/leelit/article/details/46821437

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!