AsyncTask源码分析

分析思路

从execute()方法开始分析

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

看到execute()方法接受可变参数,最多可接受三个参数;内部调用了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;
}

这里主要做了几方面的处理:
1. 判断当前要执行的任务的状态,一共三种状态,由Status枚举

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状态时,报出异常:提示该任务已执行过

  • 当任务处于PENDING状态时,可正常执行

    1. 将当前状态设置为RUNNING状态
    2. 执行onPreExecute();方法
/**
 * Runs on the UI thread before {@link #doInBackground}.
 *
 * @see #onPostExecute
 * @see #doInBackground
 */
protected void onPreExecute() {
}

该方法在doInBackground方法前边执行,可在该方法内初始化一些任务执行需要的信息
4. 调用sDefaultExecutor.execute(mFuture);执行任务

这里有两个变量需要分析:
- sDefaultExecutor
- mFuture

sDefaultExecutor分析

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

/**
 * An {@link Executor} that executes tasks one at a time in serial
 * order.  This serialization is global to a particular process.
 */
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);
        }
    }
}

sDefaultExecutor实际上就是一个SerialExecutor,一次只执行一个任务的线程池

mFuture分析

private final FutureTask<Result> mFuture;

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

mFuture是一个FutureTask实例(FutureTask是一种可以取消的异步的计算任务,有个get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。)

接下来我们查看FutureTask的构造函数:

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

上边创建mFuture时将mWorker作为callable传递进来,接着看mFuture的run()方法

public void run() {
    ......
    ......
    // 省略部分代码
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                set(result);
        }
    } finally {
        ......
        ......
        // 省略部分代码
    }
}

可以看到内部是调用了callable的call()方法,因此执行sDefaultExecutor.execute(mFuture);方法,实际上就是调用了mWorker的call()方法。接下来我们进入mWorker的call()

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

调用了doInBackground()方法
- 这是一个抽象方法,我们需要实现该方法,将需要异步执行的任务放在该方法
- 该方法在异步线程中执行
- 将execute传递进来的参数传递给doInBackground
- 执行完成会返回一个结果Result(传递进来的最后一个参数规定了结果的类型)

通过postResult来通知结果

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

该方法的主要任务是:将执行完成返回的结果封装到Message中,通过sHandler发送出去。那sHandler是什么?做了什么处理?

private static final InternalHandler sHandler = new 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;
        }
    }
}

可以看到sHandler是一个Handler类型的对象,它主要处理两种消息:
1. MESSAGE_POST_RESULT:执行完成,结束任务
2. MESSAGE_POST_PROGRESS:执行进度,通过onProgressUpdate更新任务进度

接下来跟踪下这两个常量在哪里被调用:

private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;

MESSAGE_POST_PROGRESS

搜索发现,只在publishProgress方法中用到,在这里通过sHandler发送该类型的消息

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

因此在需要更新状态的时候,我们需要调用publishProgress方法(参数为当前任务的进度);这样就会通知主线程执行onProgressUpdate方法,就可以在该方法中执行UI更新等

MESSAGE_POST_RESULT

在postResult()方法中有用到,当doInBackground执行结束后,会通知结束任务:result.mTask.finish(result.mData[0]);该方法主要是调用了AsyncTask的finish方法

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

这里主要做了两个操作:
1. 假如任务被取消,则调用onCancelled(result);方法;假如任务没被取消,则调用onPostExecute(result);方法
2. 将当前任务的状态设置为FINISHED

总结

1 AsyncTask方法

从上边的流程可以知道,在使用AsyncTask时主要涉及到以下几个方法:
1. onPreExecute():doInBackground之前执行,在主线程执行,用于初始化信息等
2. doInBackground():抽象方法,需要实现具体的操作,在子线程执行
3. publishProgress():发布任务当前进度,当调用该方法时,onProgressUpdate()方法会被调用
4. onProgressUpdate():在主线程执行,可在该方法内更新UI
5. onPostExecute():主线程执行,返回任务执行的结果

2 注意事项

  1. AsyncTask只能被执行一次,要不会报出异常
  2. 需要在主线程调用execute()方法
  • 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、付费专栏及课程。

余额充值