博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android AsyncTask源码学习
阅读量:3746 次
发布时间:2019-05-22

本文共 18014 字,大约阅读时间需要 60 分钟。

AsyncTask如何使用这篇文章就不说了,网上很多,主要学习下源码,增长下见识。

TestAsyncTask test = new TestAsyncTask();test.execute("aaa");
class TestAsyncTask extends AsyncTask
{
@Override protected Long doInBackground(String... params) { return null; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onPostExecute(Long aLong) { super.onPostExecute(aLong); } }

首先new了一个AsyncTask对象,在构造函数中发现了如下代码:

public AsyncTask() {        this((Looper) null);    }
public AsyncTask(@Nullable Looper callbackLooper) {        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()            ? getMainHandler()            : new Handler(callbackLooper);        mWorker = new WorkerRunnable
() { 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
(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); } } }; }
  1. 初始化了一个Handler,用于以后发消息。
  2. 初始化了一个WorkerRunnable对象,这个对象实现了Callable接口。
  3. 初始化了一个FutureTask对象,并且将WorkerRunnable对象传入进去。
    当运行test.execute(“aaa”)时:return executeOnExecutor(sDefaultExecutor, params);
public final AsyncTask
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; }

先会调用AsyncTask的onPreExecute方法,该方法可以做一些初始化的操作。

mWorker.mParams = params; 将WorkerRunnable对象里面的泛型Params[]赋值。
调用exec.execute(mFuture); exec对象的execute方法。
这里的exec对象为:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
该SerialExecutor对象实现了Executor接口。
Executor概述:
执行提交的Runnable任务的对象。 这个接口提供了一种将任务提交与每个任务如何运行的机制解耦的方式。
例子:

@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        testExecutor();    }    private void testExecutor() {        Executor executor = new ExecutorTest();        executor.execute(new RunnableTest1());        executor.execute(new RunnableTest2());    }    class ExecutorTest implements Executor {
@Override public void execute(@NonNull Runnable command) { if (command instanceof RunnableTest1) { command.run(); } else { new Thread(command).start(); } } } class RunnableTest1 implements Runnable {
@Override public void run() { System.out.println("RunnableTest1="+Thread.currentThread().getName()); } } class RunnableTest2 implements Runnable {
@Override public void run() { System.out.println("RunnableTest2="+Thread.currentThread().getName()); } }

输出:

I/System.out: RunnableTest1=mainI/System.out: RunnableTest2=Thread-588

书接上文

private static class SerialExecutor implements Executor {
final ArrayDeque
mTasks = new ArrayDeque
(); 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); } } }

这个类的主要作用就是同步执行,这可以作为一个学习的重点,当你学习源码的时候发现好的代码逻辑你可以(抄)记下来。

例如多个线程处理同一个对象你可以采用上面的方式:

public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Executor executor = new SerialExecutor(new DirectExecutor()); final RunnableTask1 runnableTask1 = new RunnableTask1(); for (int i = 20; i >= 0; i--) { new Thread() { @Override public void run() { executor.execute(runnableTask1); } }.start(); } } class DirectExecutor implements Executor {
public void execute(Runnable r) { new Thread(r).start(); } } class SerialExecutor implements Executor {
final Queue
tasks = new ArrayDeque
(); final Executor executor; Runnable active; SerialExecutor(Executor executor) { this.executor = executor; } public synchronized void execute(final Runnable r) { tasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (active == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((active = tasks.poll()) != null) { executor.execute(active); } } } private class RunnableTask1 implements Runnable {
int i = 20; @Override public void run() { System.out.println("RunnableTask1.run " + i--); } }}

输出:

03-10 18:45:43.035 9442-9461/? I/System.out: RunnableTask1.run  2003-10 18:45:43.035 9442-9466/? I/System.out: RunnableTask1.run  1903-10 18:45:43.035 9442-9469/? I/System.out: RunnableTask1.run  1803-10 18:45:43.035 9442-9470/? I/System.out: RunnableTask1.run  1703-10 18:45:43.035 9442-9471/? I/System.out: RunnableTask1.run  1603-10 18:45:43.045 9442-9472/? I/System.out: RunnableTask1.run  1503-10 18:45:43.045 9442-9475/? I/System.out: RunnableTask1.run  1403-10 18:45:43.045 9442-9483/? I/System.out: RunnableTask1.run  1303-10 18:45:43.045 9442-9485/? I/System.out: RunnableTask1.run  1203-10 18:45:43.045 9442-9487/? I/System.out: RunnableTask1.run  1103-10 18:45:43.045 9442-9488/? I/System.out: RunnableTask1.run  1003-10 18:45:43.045 9442-9490/? I/System.out: RunnableTask1.run  903-10 18:45:43.045 9442-9491/? I/System.out: RunnableTask1.run  803-10 18:45:43.045 9442-9492/? I/System.out: RunnableTask1.run  703-10 18:45:43.045 9442-9493/? I/System.out: RunnableTask1.run  603-10 18:45:43.045 9442-9494/? I/System.out: RunnableTask1.run  503-10 18:45:43.045 9442-9495/? I/System.out: RunnableTask1.run  403-10 18:45:43.045 9442-9496/? I/System.out: RunnableTask1.run  303-10 18:45:43.055 9442-9497/? I/System.out: RunnableTask1.run  203-10 18:45:43.055 9442-9498/? I/System.out: RunnableTask1.run  103-10 18:45:43.055 9442-9499/? I/System.out: RunnableTask1.run  0

书接上文:

这里THREAD_POOL_EXECUTOR 是一个线程池。
会执行mFuture = new FutureTask<Result>(mWorker) 这个对象的run方法,因为FutureTask也是实现了Runnable接口的。
但是你会发现new FutureTask对象并没有run方法,那是因为源码没有重写。

mFuture = new FutureTask
(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); } } };

FutureTask的run方法会调用其父类。

mFuture = new FutureTask
(mWorker) { @Override public void run() { super.run(); } };

可以看到,父类的run方法,最终会调用Callable对象的call()方法。

public FutureTask(Callable
callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
public void run() {        if (state != NEW ||            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))            return;        try {            Callable
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 { // 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); } }

调用的call方法也就是

mWorker = new WorkerRunnable
() { 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; } };

WorkerRunnable对象里面的call()方法;记住这时线程调用的,所以现在在非主线程中工作。

mTaskInvoked.set(true); 将mTaskInvoked对象设置为true,这是一个线程安全的改变。
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 设置了线程的安全级别。
重点 result = doInBackground(mParams); 调用了AsnycTask对象的doInBackground方法,该方法是运行在非UI线程中的,将结果返回给result变量,然后返回。
在finally中调用了

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

这里面getHandler就是在构造方法中初始化的Handler,运行在UI线程中。传递了一个what=MESSAGE_POST_RESULT的类型。

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

将结果封装为一个AsyncTaskResult对象。

这里面有两个what
MESSAGE_POST_RESULT:

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

判断是否调用了cancel()方法,如果调用了cancel()方法,将永远也运行不到onPostExecute()方法。

Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

Calling this method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[]) returns. Calling this method guarantees that onPostExecute(Object) is never invoked. After invoking this method, you should check the value returned by isCancelled() periodically from doInBackground(Object[]) to finish the task as early as possible.
试图取消执行此任务。 如果任务已完成,已被取消或因其他原因无法取消,此尝试将失败。 如果成功,并且此任务在调用取消时尚未开始,则此任务不应运行。 如果任务已经开始,则mayInterruptIfRunning参数确定执行此任务的线程是否应该中断以试图停止任务。
调用此方法将导致在doInBackground(Object [])返回后在UI线程上调用onCancelled(Object)。 调用此方法可确保永不调用onPostExecute(Object)。 调用此方法后,应该从doInBackground(Object [])中定期检查isCancelled()返回的值,以尽早完成任务。

public final boolean cancel(boolean mayInterruptIfRunning) {        mCancelled.set(true);        return mFuture.cancel(mayInterruptIfRunning);    }

如果用户没调用cancel方法,则会调用onPostExecute()方法,这个方法也是在UI线程中。

MESSAGE_POST_PROGRESS:
该what,是在publishProgress方法中调用。

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

最后调用onProgressUpdate()方法,用于用户更新进度,也是在UI线程中。

就这样,整个AsyncTask的调用流程就结束了。
书接上文

public void run() {        if (state != NEW ||            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))            return;        try {            Callable
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 { // 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); } }

在调用完c.call(); 方法时,将返回值赋给了result,将ran设置为true。然后执行了set(result); 方法。

protected void set(V v) {        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {            outcome = v;            U.putOrderedInt(this, STATE, NORMAL); // final state            finishCompletion();        }    }

将处理结果给了outcome

该对象可以调用get方法

public V get() throws InterruptedException, ExecutionException {        int s = state;        if (s <= COMPLETING)            s = awaitDone(false, 0L);        return report(s);    }
private V report(int s) throws ExecutionException {        Object x = outcome;        if (s == NORMAL)            return (V)x;        if (s >= CANCELLED)            throw new CancellationException();        throw new ExecutionException((Throwable)x);    }

最后调用了finishCompletion 方法:

private void finishCompletion() {        // assert state > COMPLETING;        for (WaitNode q; (q = waiters) != null;) {            if (U.compareAndSwapObject(this, WAITERS, q, null)) {                for (;;) {                    Thread t = q.thread;                    if (t != null) {                        q.thread = null;                        LockSupport.unpark(t);                    }                    WaitNode next = q.next;                    if (next == null)                        break;                    q.next = null; // unlink to help gc                    q = next;                }                break;            }        }        done();        callable = null;        // to reduce footprint    }

当整个流程都处理完之后调用来了done方法,该方法是一个空实现。

所以,在源码中:

mFuture = new FutureTask
(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); } } };

重写了done方法,并且调用了get()方法取出处理的结果。

private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }

final boolean wasTaskInvoked = mTaskInvoked.get(); 因为在调用call的时候将mTaskInvoked设为了true,所以就不在进行处理了。

微信公众号:

这里写图片描述
QQ群:365473065

你可能感兴趣的文章
一天教会三岁表弟HTML,你值得拥有
查看>>
CSS基础汇总
查看>>
SpringCloud服务注册与发现
查看>>
SpringCloud Stream 消息驱动
查看>>
SpringCloud Sleuth 分布式请求链路
查看>>
SpringCloud Alibaba 入门简介
查看>>
SpringCloud Alibaba Nacos 服务注册和配置中心
查看>>
Vue 基础总结(2.x)
查看>>
poi读写Excel
查看>>
使用Security安全框架实现权限登录
查看>>
JDBC工具类 使用Durid连接池链接MySQL数据库
查看>>
ANSYS——模态提取方法简介
查看>>
ANSYS——模态分析的载荷施加问题以及约束的施加问题
查看>>
ANSYS——初学路径之路径的定义、作用以及ansys路径模块GUI的操作解释
查看>>
ANSYS——相同模型不同创建方式的同载荷同约束下的比较
查看>>
ANSYS——网格划分的不同方法以及GUI模块的操作(自由网格、映射网格、扫掠、拖拉)
查看>>
ANSYS——命令流学习(材料属性设置、建模的命令流)
查看>>
ANSYS——杆单元简介与示例(含新版本2019版本杆实常数设置、ANSYS help的使用、单元列表使用的举例)
查看>>
ANSYS——后处理中单元表(ELEMENT table)的作用、创建、使用
查看>>
在VScode上配置golang的开发环境
查看>>