AsyncTask源码分析

1. 介绍
我们首先看下Andriod文档对AsyncTask的说明
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
大致就是说:AsyncTask可以轻松应对有关于UI线程的任务,不需要自己去控制线程和Handler就可以实现在后台执行任务、在UI主线程通知执行结果的一个类。

An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
AsyncTask为异步任务定义了三个泛型,分别是Params, Progress and Result,然后运行流程分为四步,分别是onPreExecute, doInBackground, onProgressUpdate and onPostExecute,其中泛型声明中Param代表输入参数,Progress代表执行进度,Result代表执行结果,其流程也是围绕这三个泛型参数展开,下面我们就针对AsyncTask背后的原理进行分析。

2. 源码分析
先看一个AsyncTask的使用实例

new AsyncTask<Integer, Integer, Integer>() {

            protected void onPreExecute() {
                Log.i(TAG, "onPreExecute");
            };

            @Override
            protected Integer doInBackground(Integer... arg0) {
                int result = arg0[0];
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(1000);
                        result++;
                        publishProgress(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return result;
            }

            protected void onProgressUpdate(Integer[] values) {
                Log.i(TAG, "onProgressUpdate" + values[0]);
            };

            protected void onPostExecute(Integer result) {
                Log.i(TAG, "onPostExecute" + result);
            };

        }.execute(0);

实例演示了参数Param:0 从0加至10的过程,手动Sleep线程一秒并更新进度。可以看出AsyncTask流程是由execute()方法激发的,所以源码分析就从execute()方法开始。

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

1 - 14行是对AsyncTask执行状态的一个维持,也阻止了一些非法状态。
16行调用了我们熟悉的onPreExecute(),此时所在的线程就是我们new AsyncTask所在的线程,AsyncTask的构造函数的文档说明是这样的
Creates a new asynchronous task. This constructor must be invoked on the UI thread.所以AsyncTask构造函数的执行线程环境必须是UI线程,关于为什么会有如此要求我们会在后面说明,自然onPreExecute()方法也会在UI线程中调用,此方法用来说明任务开始执行,一般在界面显示一个置为0位置的进度条。
18-19行:首先把我们传入的Param赋值给WorkerRunnable的一个实例变量,然后线程执行器开始执行一个FutureTask

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

WorkerRunnable类的定义很简单,内部仅有一个mParams实例变量
下面我们看一下WorkerRunnable和FutureTask的实例对象被创建的时机,即AsyncTask的构造函数

 public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return doInBackground(mParams);
            }
        };

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

4 - 5行:更改线程优先级,并调用doInBackground(),现在所在的线程为线程执行器中开启的子线程,所以doInBackground()执行在子线程中,该方法是任务处理的主体。

11 - 34行: FutureTask的done()方法,该方法无论任务正常结束、取消、异常结束都会调用该方法,在16行调用get()方法获得任务执行结果,并把执行结果投递到InternalHandler对应的MessageQueue队列中。
下面看下InternalHandler的定义

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

在该类中看到对各个状态的处理,这些都要在UI线程执行的方法,其中刚才说到的对执行结果的处理,是放在

  private void finish(Result result) {
        if (isCancelled()) result = null;
        onPostExecute(result);
        mStatus = Status.FINISHED;
    }

中间调用了熟悉的onPostExecute(result);该方法在UI线程中执行,该方法主要用来反馈执行结果。前面说过AsyncTask的创建必须放在UI主线程,我们现在来探究一下其原因,在UI线程中执行的方法都被放置在
InternalHandler 中处理和中转,我们看下InternalHandler 实例的创建

 private static final InternalHandler sHandler = new InternalHandler();

此处创建InternalHandler 使用的是InternalHandler 的空构造函数,

 public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;

Handler中的mLooper是通过Looper.myLooper()赋值的,该方法是获取当前所在线程的ThreadLocal中存取的Looper对象,所以当在子线程中创建AsyncTask实例的时候,在该子线程ThreadLocal并没有存入Looper,这就是为什么不能在子线程中创建AsyncTask的原因,其实并不是在子线程不能创建AsyncTask只是当前子线程不符合AsyncTask的条件。
在doInBackground()方法中有时要更新执行进度,会调用

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

然后经过Handler中转到UI线程中调用onProgressUpdate方法

3. 结束语
这样关于AsyncTask的源码分析就结束了,可以看出AsyncTask也是基于Handler机制的中转,中间解释了AsyncTask不能在子线程中创建的原因,在以后的博客中会对AsyncTask进行更改使其支持在子线程创建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android网络连接源码分析主要涉及到Android系统中网络连接的相关实现和机制。下面是Android网络连接的源码分析: 1. 网络连接管理类:Android中的网络连接管理由ConnectivityManager类负责。该类提供了获取网络状态、监听网络状态变化等功能。其源码位于frameworks/base/core/java/android/net/ConnectivityManager.java。 2. 网络请求类:Android中的网络请求由HttpClient或HttpURLConnection实现。在Android 6.0及以上版本中,Google推荐使用HttpURLConnection。HttpClient的源码位于frameworks/base/core/java/org/apache/http/impl/client/DefaultHttpClient.java,HttpURLConnection的源码位于libcore/luni/src/main/java/java/net/HttpURLConnection.java。 3. 网络请求处理类:Android中的网络请求处理由AsyncTask或者Thread实现。AsyncTask是一个封装了线程池和Handler的异步任务类,用于在后台执行耗时操作,并在主线程更新UI。其源码位于frameworks/base/core/java/android/os/AsyncTask.java。 4. 网络请求结果处理类:Android中的网络请求结果处理由Handler或者Callback实现。Handler用于在主线程中处理异步任务的结果,Callback则是一种回调机制,用于在异步任务完成后执行相应的操作。 5. 网络缓存类:Android中的网络缓存由DiskLruCache或者LruCache实现。DiskLruCache用于将网络请求结果缓存到本地磁盘,LruCache则是一种内存缓存机制,用于缓存网络请求结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值