AsyncTask源码分析

Android  Java  源码分析  2018年6月1日 pm8:52发布6年前 (2018)更新 91es.com站长
65 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.91es.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、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

WordPress部分内容输入密码可见

1、将以下代码添加到Three主题的functions.php文件最后一个?>的前面。/* Name: 部分内容输入密码可见(短代码) * 作者:E享乐(www.exiang2.com) */function e_secret($atts, $content=null){ ex...

木心 :至少,每天要看书

不要讲文学是崇高伟大的。文学可爱。大家课后不要放弃文学。文学是人学。至少,每天要看书,开始读书,要浅,浅到刚开始就可以居高临下。一上来听勃拉姆斯第一交响乐,你会淹死。一开始听《圣母颂》、《军队进行曲》,很好。我小时候听这些,后来到杭州听贝多芬的《月光奏鸣曲》,居然完全不懂,对西方,一开始从基督教...

[摘]Android异常和性能优化 - OOM异常

什么是OOMOOM全称为“Out of memory”异常,从名字上可以理解就是内存耗尽了。在android当中,android系统会给每个APP设立一个独立的工作区间,也就是Dalvik虚拟机空间,这样使每个APP在独立的空间运行而不受影响。但是android系统为每一个Dalvik虚拟机都设定...

JNI之数组简单操作

前言简单记录一下JNI中数组操作。正文public class Hello {   static {       System.loadLibrary("Hello");   }   // JNI中对数组排序   public static native int[] so...

JNI之函数介绍三之字符串操作

前言今天介绍一下JNI中字符串相关操作函数。正文NewStringjstring NewString(JNIEnv *env, const jchar *unicodeChars,jsize len);利用 Unicode 字符数组构造新的 java.lang.String 对象。un...

乔叶:畏惧告别

我实际上是个十分口拙的人。而且,特别是在关键时刻尤为口拙。比如告别。告别似乎是一个普遍公认的隆重时刻,也是一个最能够让人感怀的时刻。越是这样的时刻,我就越是畏惧。倒不是怕伤心怕落泪,而是怕说话。——人多还好,你一句我一句也容易混过。最怕人少,尤其是只有两个人的时候,无论语言的茅草多么丰盛,也总会有...