AsyncTask源码分析

Android  Java  源码分析  2018年6月1日 pm8:52发布7年前 (2018)更新 城堡大人
86 0 0

AsyncTask源码分析,当前使用的Android 6.0的代码,AsyncTask源码目录在如下:

base\core\java\android\os\AsyncTask.java

在分析源码之前,我们看看我们在项目中是如何使用AsyncTask的。

下面是个简单的demo,只是写了AsyncTask使用的大致步骤。(AsyncTask是个抽象类,因此需要我们继承并实现其抽象方法doInBackground())

	/**
	 * 实现AsyncTask
	 *
	 * @author
	 *
	 */
	private class MyAsyncTask extends AsyncTask<String, Void, Void> { //这里只是参数,不返回结果,所以后面的参数设置为Void

		@Override
		protected Void doInBackground(String... params) {
			// TODO Auto-generated method stub
			   // 后台运行线程
                           publishProgress(); //5.更新进度值.调用此句后才会执行onProgressUpdate()
			return null;
		}

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			// 主线程,源码中特意注明
			super.onPreExecute();
		}

		@Override
		protected void onProgressUpdate(Void... values) {
			// TODO Auto-generated method stub
			// 主线程,更新进度
			super.onProgressUpdate(values);
		}

		@Override
		protected void onPostExecute(Void result) {
			// TODO Auto-generated method stub
			// 主线程,返回结果
			super.onPostExecute(result);
		}

	}

	//仅仅简单测试,如果要访问网络,需要配置网络权限
	String url = "http://www.biumall.com/index.html";
	MyAsyncTask myAsyncTask = new MyAsyncTask();  //[1.AsyncTask构造函数初始化]
	myAsyncTask.execute(url);[2.execute()运行]

1. AsyncTask构造函数初始化

MyAsyncTask myAsyncTask = new MyAsyncTask();

MyAsyncTask的初始化直接调用了父类的AsyncTask的默认构造函数

   /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        //[1.1 WorkerRunnable实现了Callable接口]
        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); //[1.2 doInBackground()方法在这里调用]
                Binder.flushPendingCommands();
                return postResult(result); //[1.3 psotResult() ]
            }
        };
        //[1.4 FutureTask ]
        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() { //Callable在call()方法中返回的结果在这里通过get()方法获取,然后postResultIfNotInvoked()范湖结果
                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.1 WorkerRunnable实现了Callable接口
    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

Callable也是类似也Runnable,call()运行在子线程中

具体了解Callable的使用,请访问《Callable的简单使用

1.2 doInBackground()的调用

doInBackground()计算是运行在WorkerRunnable中的call()中的,但此DoInBackground()方法是个抽象的,所以子类必须实现

    /**
     * Override this method to perform a computation on a background thread. The
     * specified parameters are the parameters passed to {@link #execute}
     * by the caller of this task.
     *
     * This method can call {@link #publishProgress} to publish updates
     * on the UI thread.
     *
     */
    @WorkerThread
    protected abstract Result doInBackground(Params... params);

doInBackground()运行在工作线程(子线程)中的,抽象方法,我们会在实现类(demo中的MyAsyncTask类中)中进行复杂耗时计算。

在这个方法中我们可以调用publishProgress调用这个方法把工作线程的计算进度发送到主线程中更新UI,并回调onProgressUpdate()这个方法

    /**
     * Runs on the UI thread after {@link #publishProgress} is invoked.
     * The specified values are the values passed to {@link #publishProgress}.
     *
     * @param values The values indicating progress.
     *
     * @see #publishProgress
     * @see #doInBackground
     */
    @SuppressWarnings({"UnusedDeclaration"})
    @MainThread
    protected void onProgressUpdate(Progress... values) {
    }

在onProgressUpdate()方法中我们可以更新UI界面和提示计算进度(友好提示)

在工作线程中计算后,需要把结果传给主线程,我们继续

1.3 postResult()
   private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        //handler消息机制
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, //[1.5 Handler消息机制返回计算结果]
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

在postResult()中,我们看到了Handler机制,,,也就是说,工作线程和子线程通信还是通过Handler机制来的。

在WorkRunnable中的call()方法是会返回Result的,这个值可以通过FutureTask的get()方法获取的。

1.4 FutureTask

在FutureTask中,等到WorkRunnable计算完后,会调用postResultIfNotInvoked(),直接进入源码

    public final Result get() throws InterruptedException, ExecutionException {
        return mFuture.get();
    }

get()方法里运行的就是Future.get()方法。这里会等到WorkRunnable计算结果,一直阻塞。

    private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, //[1.5 Handler消息机制返回计算结果]
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

最后还是走到postResult()中,,,又跟Handler消息机制挂上钩了。

1.5 Handler消息机制返回计算结果
    private void finish(Result result) {
        if (isCancelled()) {//如果取消了,就不返回结果;反之把结果返回到onPostExecute()这个方法我们在实现AsyncTask中时重写
            onCancelled(result);
        } else {
            onPostExecute(result); //返回到主线程了
        }
        mStatus = Status.FINISHED;
    }

    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]); //[看finish()方法中的定义]
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData); //[这个是更新进度状态,在doInBackground()中调用publishProgress()]
                    break;
            }
        }
    }

上面只是根据代码分析,并没有根据实际运行流程走。通过上面我们知道AsyncTask中工作线程和主线程交互依旧使用Handler消息机制的。

2. execute()方法执行

AsyncTask构造函数初始化后,我们调用execute()方法运行程序的。

myAsyncTask.execute(url);[2.execute()运行]

我们进入execute()方法

    /**
     * Executes the task with the specified parameters. The task returns
     * itself (this) so that the caller can keep a reference to it.
     */
    @MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

execute()方法中并没有做任何处理,而是直接调用了executeOnExecutor()方法

    /**
     * Executes the task with the specified parameters. The task returns
     * itself (this) so that the caller can keep a reference to it.
     */
    @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
           //判断当前AsyncTask的状态,有三种状态
        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(); //执行onPreExecute()代码,这个是运行我们重写的onPreExecute()方法

        mWorker.mParams = params; //设置传入的参数
        exec.execute(mFuture); //[2.1 开启工作线程]

        return this;
    }

在executeOnExecutor()方法中,就行了当前AsyncTask的状态判断。

AsyncTask中有三种状态

    /**
     * Indicates the current status of the task. Each status will be set only once
     * during the lifetime of a task.
     */
    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,
    }

如果此时是RUNNING或者FINISHED,再次运行AsyncTask时就会抛出异常。

2.1 开启工作线程

exec.execute(mFuture);中的exec就是SerialExecutor 的对象,而SerialExecutor 继承于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);
            }
        }
    }

在run()方法中就运行了mFuture.run(),最后一定会执行scheduleNext(),不过最终调用的都是线程池

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

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

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

到这里就运行工作线程了,然后通过FutureTask.get()获取计算结果,再返回结果,AsyncTask就基本分析结束了。

 历史上的今天

  1. 2023: system.exit()的作用(0条评论)
  2. 2021: 纪伯伦:你的孩子其实不是你的孩子(0条评论)
  3. 2020: Android Studio将lib项目打包成jar和aar(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

Android Studio混淆aar包记录

前言本文记录一使用Android studio 混淆的使用,这里以打包aar为例。正文AS中创建一个library模块,这里假设为SkinLib打开混淆配置/SkinLib/build.gradle中,打开混淆配置,这里只配置了release的混淆,debug版本是没有配置的,如果你想都...

ACTION_MEDIA_BUTTON监听的几种方式记录

前言记录一下,MEDIA_BUTTON监听,用来控制多媒体的上下曲,播放暂停等正文隐藏内容!付费阅读后才能查看!¥3多个隐藏块只需支付一次付费阅读参考文章该文章太久了,忘记出处了,抱歉。

梁实秋:时间即生命

最令人怵目惊心的一件事,是看着钟表上的秒针一下一下的移动,每移动一下就是表示我们的寿命已经缩短了一部分。再看看墙上挂着的可以一张张撕下的日历,每天撕下一张就是表示我们的寿命又缩短了一天。因为时间即生命。没有人不爱惜他的生命,但很少人珍视他的时间。如果想在有生之年做一点什么事,学一点什么学问,充实自己...

The key must be an application-specific resource id

前言在做ListView+Adapter时,为了重复利用convertView,如下if (null != convertView) {   viewHolder = (ViewHolder) convertView.getTag(TAG_VIEW_MEDIA);} else {   ...

王小波:人为什么活着

银河,你好!我在家里给你写信。你问我人为什么活着,我哪能知道啊?我又不是牧师。释迦牟尼为了解决这个问题出了家,结果得到的结论是人活着为了涅,就是死。这简直近乎开玩笑了。不过活着总得死,这一点是不错的,我有时对这一点也很不满意呢。还有人活着有时候有点闷,这也是很不愉快的。过去我想,人活着都得为别人...

framework中添加自己的aidl

前言简单记录一下在Framework中新增一个服务接口,方便应用调用,类似于获取AudioManager一样。AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);Android...