美文网首页
AsyncTask原理分析

AsyncTask原理分析

作者: _风听雨声 | 来源:发表于2020-04-10 16:15 被阅读0次

引言

在打算写分析AsyncTask这篇文章之前,比较犹豫要不要写这篇文章。因为AsyncTask目前的开发中基本已经不用了,市面上有太多更优秀的替代方案。但是看了AsyncTask的源码之后,其实还是有很多的可取之处。包括目前市面上很多的更好的替代方案,同样是用的AsyncTask的线程池和线程切换的这套机制,只是加以优化和改进。

基本使用

class Task extends AsyncTask<String,Integer ,String>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... strings) {
            publishProgress();//设置进度
            return null;
        }
        
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }
    }
通常实现的方法

1.onPreExecute(),运行在主线程,在任务执行前,做一些初始化的操作
2.doInBackground(),运行在工作线程,耗时操作放在这个方法
3.onProgressUpdate(),更新进度,运行在主线程,在耗时操作中调用publishProgress()返回当前进度
4.onPostExecute(),任务执行完毕时调用,运行在主线程,返回结果


源码分析

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

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

        return this;
    }

在executeOnExecutor()方法中,可以看到AsycnTask有三种状态,Status.PENDING(未执行)、Status.RUNNING(执行中)、Status.FINISHED(执行完毕)。只要不是未执行状态,去调用executeOnExecutor()都会报错IllegalStateException,这也是AnyncTask只能execute一次的原因。再看到onPreExecute(),这就是运行在主线程做初始化的那个方法。

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

mWorker、exec和mFuture分别是

@UnsupportedAppUsage
private final WorkerRunnable<Params, Result> mWorker;
@UnsupportedAppUsage
private final FutureTask<Result> mFuture;
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内部维护了一个ArrayDeque的队列,并将runable任务加入线程池。再看下AysncTask的构造方法

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

在构造方法中,先实例化了一个主线程的hanlder,mWorker也在这里实例化, mWorker是WorkerRunnable类型的实例化对象。

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

WorkerRunnable实现了Callable,Callable可以认为是一个升级版可以返回结果还能抛出异常的Runable,Callable通常和Future配合使用。在实例化的WorkerRunnable的时候,调用了result = doInBackground(mParams),执行了doInBackground方法中的耗时操作并返回,返回调用了postResult(Result result)。

    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 {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

使用handler将doInBackground()返回的结果发送到主线程,并调用了onPostExecute(result)将结果返回。那mFuture是用来干嘛的呢?接着往下看

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);
                }
            }
        };
private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

mFuture会等待WorkerRunnable也就是Callable执行返回的结果,如果在前面的WorkerRunnable,结果没有返回成功,这里会再postResult(),将结果返回发送到主线程给AsyncTask的onPostExecute()方法。

相关文章

  • AsyncTask工作原理

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

  • 详细解读AsyncTask的黑暗面以及一种替代方案

    基于最新版本的AsyncTask详细解读主要是一些AsyncTask的原理解读,本篇将分析AsyncTask使用的...

  • Asynctask原理分析

    Asynctask是一种轻量级异步任务类,任务是在线程池中执行后台任务的,并将结果返回到UI界面。它封装了hand...

  • AsyncTask原理分析

    -----基于Android6.0分析AsyncTask是一个抽象类,我们去使用它的时候需要创建一个子类继承它。它...

  • AsyncTask原理分析

    AsyncTask在安卓中常用于线程间通信。在子线程执行耗时任务,在主线程更新UI。 AsyncTask内部封装了...

  • AsyncTask原理分析

    线程池ThreadPoolExecutorJDK5带来的一大改进就是Java的并发能力,它提供了三种并发武器:并发...

  • AsyncTask原理分析

    以下分析基于android-27 AsyncTask使用方法 2.在新建对象时候主要调用 执行execute()的...

  • AsyncTask原理分析

    引言 在打算写分析AsyncTask这篇文章之前,比较犹豫要不要写这篇文章。因为AsyncTask目前的开发中基本...

  • AsyncTask工作原理分析

    AsyncTask 相信大家对他的使用并不陌生,它是谷歌官方提供的一种轻量级别的异步任务类,底层封装的是两个线程池...

  • 自定义一个AsyncTask

    上一篇我们分析类AsyncTask原理,但想要真正的掌握还是要动手自己实现一个AsyncTask,下面我们就开始参...

网友评论

      本文标题:AsyncTask原理分析

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