AsyncTask原理分析

单个网络请求更新UI用Handler比较方便,但多个网络请求处理最好使用AsyncTask。

核心方法

  • onPreExecute():在主线程中执行。一般在任务执行前做准备工作,比如对 UI 做一些标记。
  • doInBackground(Params...params):在线程池中执行。在 onPreExecute方法执行后运行,用来执行较为耗时的操作。在执行过程中可以调用publishProgress(Progress...values)来更新进度信息。
  • onProgressUpdate(Progress...values):在主线程中执行。当调用 publishProgress(Progress...values)时,此方法会将进度更新到UI组件上。
  • onPostExecute(Result result):在主线程中执行。当后台任务执行完成后,它会被执行。doInBackground方法得到的结果就是返回的result的值。此方法一般做任务执行后的收尾工作,比如更新UI和数据。

核心成员

  • WorkerRunnable:AsyncTask在构造方法中初始化的类,实现了Callable接口并实现了其call方法。call方法内部调用了doInBackground方法来处理任务并得到结果,并最终调用postResult将结果投递出去
  • FutureTask:这是一个可管理的异步任务,它实现了Runnable和Futrue这两个接口。因此,它可以包装 Runnable和Callable,并提供给Executor执行。在这里WorkerRunnable作为参数传递给了FutureTask,用来监视目标线程调用call()方法的情况,例如用 Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法返回结果
  • THREAD_POOL_EXECUTOR:执行具体网络请求的线程池,其核心线程和线程池允许创建的最大线程数都是由CPU的核数来计算出来的。它采用的阻塞队列是LinkedBlockingQueue,容量为128。
  • SerialExecutor :管理请求任务的线程池,内部维护了一个根据元素数量调节容量的双向队列ArrayDeque,作用是ArrayDeque负责存储请求,并串行执行请求任务
  • Handler:负责将结果数据传递给UI线程以便更新UI

大致流程原理=两个线程池+Handler

  1. 首先在AsyncTask的构造函数里初始化了一个WorkerRunnable,它实现了Callable接口并实现了其call方法。call方法内部调用了doInBackground方法来处理任务并得到结果,并最终调用postResult将结果投递出去;另外还初始化了一个FutureTask,它是worker的包装类,用来监视目标线程调用call()方法的情况,例如用 Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法返回结果。
    public AsyncTask(@Nullable Looper callbackLooper) {
            mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
    
            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);
                    }
                }
            };
        }
  2. 声明完AsyncTask的实例后,在理想情况下,就可以调用execute()方法来执行请求任务了。
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
    
        @MainThread
        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();
            //将参数赋值到上一步初始化的WorkerRunnable里
            mWorker.mParams = params;
            //此exec是SerialExecutor
            exec.execute(mFuture);
            return this;
        }

    可以看到AsyncTask的execute方法最后执行的是exec.execute(mFuture)方法,也就是SerialExecutor的execure方法

  3. SerialExecutor是一个串行的线程池,当调用SerialExecutor的execute方法时,会将FutureTask加入到mTasks中。当任务执行完或者当前没有活动的任务时都会执行scheduleNext方法,它会从mTasks取出FutureTask任务并交由 THREAD_POOL_EXECUTOR 处理。

    private static class SerialExecutor implements Executor {
    
            //双向队列存储请求任务
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            Runnable mActive;
    
            //synchronized保证请求的串行执行,这里区别于Android3.0之前的版本,之前是并行,会有问题
            public synchronized void execute(final Runnable r) {
                mTasks.offer(new Runnable() { //队列的offer方法将请求添加到队列中
                    public void run() {
                        try {
                            //这里执行的是FutureTask的run方法,最终执行WorkerRunnable的call方法
                            r.run(); 
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
  4. WorkerRunnable的call方法内部调用了doInBackground方法来处理任务并得到结果,并调用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 class InternalHandler extends Handler {
            public InternalHandler(Looper looper) {
                super(looper);
            }
    
            @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 {
                //更新UI
                onPostExecute(result);
            }
            mStatus = Status.FINISHED;
        }

     

Android 3.0前后 AsyncTask的区别

  • 3.0版本之前的AsyncTask是并行处理任务,所以缺点就是线程池最大的线程数为128,加上阻塞队列的10个任务,AsyncTask最多能同时容纳138个任务,当提交第139个任务时就会执行饱和策略,默认抛出RejectedExecutionException(拒绝执行)异常。
  • 3.0及以上版本用SerialExecutor作为默认的线程,它将任务串行处理,保证一个时间段只有一个任务执行,因此Android 3.0之前版本的缺点在Android 3.0之后的版本中不会出现,因为线程是一个接一个执行的,不会出现超过任务数而执行饱和策略的情况。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书是一本Android进阶类书籍,采用理论、源码和实践相结合的方式来阐述高水准的Android应用开发要点。本书从三个方面来组织内容。第一,介绍Android开发者不容易掌握的一些知识点;第二,结合Android源代码和应用层开发过程,融会贯通,介绍一些比较深入的知识点;第三,介绍一些核心技术和Android的性能优化思想。 第1章 Activity的生命周期和启动模式 1 1.1 Activity的生命周期全面分析 1 1.1.1 典型情况下的生命周期分析 2 1.1.2 异常情况下的生命周期分析 8 1.2 Activity的启动模式 16 1.2.1 Activity的LaunchMode 16 1.2.2 Activity的Flags 27 1.3 IntentFilter的匹配规则 28 第2章 IPC机制 35 2.1 Android IPC简介 35 2.2 Android中的多进程模式 36 2.2.1 开启多进程模式 36 2.2.2 多进程模式的运行机制 39 2.3 IPC基础概念介绍 42 2.3.1 Serializable接口 42 2.3.2 Parcelable接口 45 2.3.3 Binder 47 2.4 Android中的IPC方式 61 2.4.1 使用Bundle 61 2.4.2 使用文件共享 62 2.4.3 使用Messenger 65 2.4.4 使用AIDL 71 2.4.5 使用ContentProvider 91 2.4.6 使用Socket 103 2.5 Binder连接池 112 2.6 选用合适的IPC方式 121 第3章 View的事件体系 122 3.1 View基础知识 122 3.1.1 什么是View 123 3.1.2 View的位置参数 123 3.1.3 MotionEvent和TouchSlop 125 3.1.4 VelocityTracker、GestureDetector和Scroller 126 3.2 View的滑动 129 3.2.1 使用scrollTo/scrollBy 129 3.2.2 使用动画 131 3.2.3 改变布局参数 133 3.2.4 各种滑动方式的对比 133 3.3 弹性滑动 135 3.3.1 使用Scroller 136 3.3.2 通过动画 138 3.3.3 使用延时策略 139 3.4 View的事件分发机制 140 3.4.1 点击事件的传递规则 140 3.4.2 事件分发的源码解析 144 3.5 View的滑动冲突 154 3.5.1 常见的滑动冲突场景 155 3.5.2 滑动冲突的处理规则 156 3.5.3 滑动冲突的解决方式 157 第4章 View的工作原理 174 4.1 初识ViewRoot和DecorView 174 4.2 理解MeasureSpec 177 4.2.1 MeasureSpec 177 4.2.2 MeasureSpec和LayoutParams的对应关系 178 4.3 View的工作流程 183 4.3.1 measure过程 183 4.3.2 layout过程 193 4.3.3 draw过程 197 4.4 自定义View 199 4.4.1 自定义View的分类 200 4.4.2 自定义View须知 201 4.4.3 自定义View示例 202 4.4.4 自定义View的思想 217 第5章 理解RemoteViews 218 5.1 RemoteViews的应用 218 5.1.1 RemoteViews在通知栏上的应用 219 5.1.2 RemoteViews在桌面小部件上的应用 221 5.1.3 PendingIntent概述 228 5.2 RemoteViews的内部机制 230 5.3 RemoteViews的意义 239 第6章 Android的Drawable 243 6.1 Drawable简介 243 6.2 Drawable的分类 244 6.2.1 BitmapDrawable 244 6.2.2 ShapeDrawable 247 6.2.3 LayerDrawable 251 6.2.4 StateListDrawable 253 6.2.5 LevelListDrawable 255 6.2.6 TransitionDrawable 256 6.2.7 Ins

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值