AsyncTask源码探索

AsyncTask源码探索

这里写代码片

知识点:

Executors:

提供了一系列静态工厂方法用于创建各种线程池,不了解的可以看一下
java并发编程–Executor框架

SerialExecutor

实现了Executors 接口,因为他的存在AsyncTask变成了串行的了,当然你也可以自己变成并行,不过并行的一个报错,其他的都会受印象。

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

ArrayDeque,是一个新的数据结构,Deque一看你就要明白就是一个队列,队列呢,可以理解为排队一样的,先进先出,这就是为什么串行的意思。

Runnable,Callable、Future和FutureTask

关于这三个呢,简单介绍下吧,后面代码中出现的挺多的

  • Runnable 无返回值
  • Callable 可有返回值返回
  • Future 可进行获取,取消,判断是否完成
  • FutureTask是基本的实现了Future和runnable接口
    • 实现runnable接口,说明可以把FutureTask实例传入到Thread中,在一个新的线程中执行。
    • 实现Future接口,说明可以从FutureTask中通过get取到任务的返回结果,也可以取消任务执行(通过interreput中断)
      -onCancelled 任务被取消回调方法

不太清楚的可以看下下面资料

Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)

用法:

 private class DownloadTask extends AsyncTask<String, Object, Long> {
    @Override
    protected void onPreExecute() {
    }

    @Override
    protected Long doInBackground(String... params) {
      return null;
    }

    //下载文件后返回一个Object数组:下载文件的字节数以及下载的博客的名字
    private Object[] downloadSingleFile(String str){
      //Object[] result=new Object[];
      return null;
    }

    @Override
    protected void onProgressUpdate(Object... values) {
    }

    @Override
    protected void onPostExecute(Long aLong) {
    }

    @Override
    protected void onCancelled() {
    }
  }


  DownloadTask downloadTask = new DownloadTask();
  downloadTask.execute(""); 

AsyncTask 传入参数

  1. 在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
  2. 后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位
  3. 当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

AsyncTask 方法

onPreExecute()

执行AsyncTask任务之前回调的方法,你可以显示一个加载框

doInBackground(Params…)

执行耗时操作的回调,此时已经在子线程

onProgressUpdate(Progress…)

当在后台任务中调用了publishProgress(Progress…)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。

onPostExecute(Result)

doInBackground执行完耗时操作以后的结果会在这个方法回调回来,此事已经在主线程,你可以执行UI渲染等等

回到源码中,先看execute方法,执行AsyncTask任务的方法

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


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

Status.RUNNING,是来保证这个任务已经在运行中,如果在运行就会报错,mStatus默认是Status.PENDING

接下来也就是执行onPreExecute();也就是耗时之前回调的方法

接下来出现的mWorker? mFuture? 是啥? execute还把我们传入参数给了mWorker
还有一个可以确定的是Executor.execute(mFuture)

mFuture是在子线程运行的,继续猜下去,doInBackground肯定在里面

我之前一直没有说的是AsyncTask的构造方法是什么

构造方法
 public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    postResult(result);
                }
                return result;
            }
        };

        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 occurred while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

WorkerRunnable中,终于看到了doInBackground了,这里回调给使用者,开始执行耗时操作,执行完了结果被传入了postResult();

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

    private static Handler getHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler();
            }
            return sHandler;
        }
    }

  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;
            }
        }
    }
    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

其实说到这里,继续猜,子线程得有handler去把值传到主线程,然后去回调吧,代码就这里.

getHandler就是得到了一个handler,而handler中就有onProgressUpdate回调方法,但是呢,这个流程并没有走onProgressUpdate回调方法,为什么后面再讲
再看finish

finish中,如果取消了就会回调取消方法,如果没有就结束了.

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

ok,前面买的坑就在于这里,你可以调用这个方法,传入进度值,就可以回调到onProgressUpdate,你只能在doInBackground中掉用哦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值