美文网首页
AsyncTask源码分析

AsyncTask源码分析

作者: 风月寒 | 来源:发表于2020-10-07 14:39 被阅读0次
AsyncTask的使用
/**
 * 避免内存泄露,用弱引用包裹,加静态内部类的方式处理
  */
//输入的参数 String  执行进度 Integer 返回的结果  String
// a. Params:开始异步任务执行时传入的参数类型,对应excute()中传递的参数
// b. Progress:异步任务执行过程中,返回下载进度值的类型
// c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致
static class MyAsynTask extends AsyncTask<String,Integer,String>{
         
         private WeakReference<ProgressBar> progressBarWeakReference;
         private WeakReference<TextView> textViewWeakReference;

         public  MyAsynTask(ProgressBar progressBar,TextView textView){
             progressBarWeakReference = new WeakReference<>(progressBar);
             textViewWeakReference = new WeakReference<>(textView);
         }


        @Override
        protected void onPreExecute() {
            TextView textView = textViewWeakReference.get();
            textView.setText("加载中");
        }

        @Override
        protected String doInBackground(String... strings) {
            try {
                int count = 0;
                while (count <= 100){
                    Thread.sleep(1000);
                    count += 1;
                    publishProgress(count);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            ProgressBar progressBar = progressBarWeakReference.get();
            progressBar.setProgress(values[0]);
            TextView textView = textViewWeakReference.get();
            textView.setText("Loading.."+ values[0] + "%");
        }

        @Override
        protected void onPostExecute(String s) {
            TextView textView = textViewWeakReference.get();
            textView.setText("加载完毕");
        }

        @Override
        protected void onCancelled() {
            TextView textView = textViewWeakReference.get();
            textView.setText("已取消");
            ProgressBar progressBar = progressBarWeakReference.get();
            progressBar.setProgress(0);
        }
    }
    
    /**
     * 在onDestroy的时候取消任务
     */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMyAsynTask.cancel(true);
    }
源码分析
mMyAsynTask.execute();

调用execute启动任务。

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

从上面可以知道有一个@MainThread注解,表面该方法只能在主线程执行。

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

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }
    
    @UnsupportedAppUsage
    private volatile Status mStatus = Status.PENDING;
    
    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,
    }

首先判断状态,总共有三种状态,分别为PENDING,RUNNING,FINISHED。默认的为PENDING,当执行executeOnExecutor方法时,将状态改为RUNNING。

这也是一个==AsyncTask对象不能被多次执行的原因。== 因为执行executeOnExecutor()时,只要初始状态不是PENDING就会报错。

最后执行exec.execute(mFuture)。其中exec是sDefaultExecutor,下面来看一下sDefaultExecutor。

private static volatile Executor sDefaultExecutor = SERIAL_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);
            }
        }
    }

SerialExecutor 内部维持了一个队列,通过锁使得该队列保证AsyncTask中的任务是串行执行的,即多个任务需要一个个加到该队列中。加入的这个任务就是mFuture。

exec.execute(mFuture)实际上是先向ArrayDeque这个队列中加入mFuture这个任务。然后调用scheduleNext(),调用THREAD_POOL_EXECUTOR执行队列头部的任务。

mFuture = new FutureTask<Result>(mWorker)

在加入时会执行r.run(),即执行mFuture.run().

public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();//1
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
    
    //构造函数
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

由构造函数我们可以知道,传入的callable就是mWorker。

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.run()的run()方法中,会执行//1处,即执行mWorker.call()。在call方法中,先执行完doInBackground()方法,又执行postResult()方法。

THREAD_POOL_EXECUTOR实际是个线程池,开启了一定数量的核心线程和工作线程。然后调用线程池的execute()方法。执行具体的耗时任务,即开头构造函数中mWorker中call()方法的内容。由此可知,真正执行耗时任务的是THREAD_POOL_EXECUTOR。SerialExecutor只是将任务加入其中。

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

然后通过Handler将耗时操作返回的结果放到主线程。

private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }
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;
            }
        }
    }   
    
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);
            

private Handler getHandler() {
    return mHandler;
}

这里使用sHandler对象发出了一条消息,消息中携带了MESSAGE_POST_RESULT常量和一个表示任务执行结果的AsyncTaskResult对象。这里对消息的类型进行了判断,如果这是一条MESSAGE_POST_RESULT消息,就会去执行finish()方法,如果这是一条MESSAGE_POST_PROGRESS消息,就会去执行onProgressUpdate()方法。

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

可以看到,如果当前任务被取消掉了,就会调用onCancelled()方法,如果没有被取消,则调用onPostExecute()方法,这样当前任务的执行就全部结束了。

然后将状态变成FINISHED。

在3.0以前,最大支持128个线程的并发,10个任务的等待,同时执行138个任务是没有问题的;而超过138会马上出现java.util.concurrent.RejectedExecutionException。在3.0以后,无论有多少任务,都会在其内部单线程执行;

如果想让AsyncTask在3.0以上的系统中并行: 调用AsyncTask的executeOnExecutor方法而不是execute方法

btn_a.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new MyTask("AsyncTask#1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                new MyTask("AsyncTask#2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                new MyTask("AsyncTask#3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                new MyTask("AsyncTask#4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                new MyTask("AsyncTask#5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
            }
        });
        
2020-10-07 14:32:59.341 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#2execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.342 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#1execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#4execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#3execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#5execute finish at 2020-10-07 14:32:59

相关文章

  • Android源码解析-Asynctask

    android源码分析-AsyncTask 我们一般创建一个AsyncTask的任务代码如下: 下面开始分析源码:...

  • AsyncTask异步任务类

    目录介绍 01.先看下AsyncTask用法 02.AsyncTask源码深入分析2.1 构造方法源码分析2.2 ...

  • AsyncTask源码分析

    前言 IntentService使用及源码分析 HandlerThread源码分析 AsyncTask使用及封装实...

  • AsyncTask 使用及封装实践

    前言 IntentService使用及源码分析 HandlerThread源码分析 AsyncTask使用及封装实...

  • Android - AsyncTask (SDK 24)

    利用AsyncTask给ListView异步加载图片 实现图文混排 链接 AsyncTask源码分析 知乎

  • 4.AsyncTask使用,原理

    资料 AsyncTask处理机制详解及源码分析-工匠若水 AsyncTask 源码解析-鸿洋 带你认识不一样的As...

  • AsyncTask带你更深入点看源码

    关键词 AsyncTask源码分析 FutureTask源码分析 快过年了,公司同事已经开始进行迁移之旅,目前来...

  • AsyncTask工作原理

    AsyncTask工作原理调用图 AsyncTask工作原理源码分析,建议配合调用图一起看 调用 AsyncTas...

  • AsyncTask源码分析

    一 AsyncTask使用的场景 在MainThread线程中执行耗时不长的最多几秒钟的后台工作。 二 Async...

  • AsyncTask源码分析

    Android中UI的更新主要在主线程中,而耗时操作一般在子线程中进行;我们可以通过handler发送消息的方式处...

网友评论

      本文标题:AsyncTask源码分析

      本文链接:https://www.haomeiwen.com/subject/sfmfpktx.html