Android之AsyncTask源码分析(第二篇:创建对象)

(注意:本文基于API 28的源码分析,API 29上或其他平台的源码略有不同) 

前言

    无参的构造方法用于创建AsyncTask对象(AsyncTask是抽象类,只能创建子类的对象),另外两个有参数的构造方法是hide修饰的,我们无法直接调用!

 

AsyncTask()构造方法分析

    public AsyncTask() {
        this((Looper) null);
    }

null强制转换为Looper,然后传入只有1个参数的构造方法中。传入参数的方式,真是神奇了……

 

AsyncTask()构造方法分析(重载构造方法:1个参数)

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

传入的参数为Looper对象

1、为AsyncTask对象持有的mHandler进行初始化,可能会出现的两种情况

第一:AsyncTask对象持有一个Handler对象mHandler,当传入的callbackLooper为null或者callbackLooper为主线程的Looper对象时,会调用一个getMainHandler()方法,getMainHandler()方法返回的Handler对象由mHandler负责持有,这个Handler对象是主线程的Handler对象

第二:callbackLooper即不为null、也不是主线程的Looper对象时,则会通过new一个新的Handler对象,同样由mHandler负责持有

2、为AsyncTask对象持有的mWorker进行初始化

首先创建一个WorkerRunnable对象,该对象是以匿名内部类形式创建的,在匿名内部类中重写的call()方法中做了什么呢?这个在后面后解释。WorkerRunnable类实现了Callable接口,最终这个创建的WorkerRunnable对象由AsyncTask对象持有的mWorker负责持有

3、为AsyncTask对象持有的mFuture进行初始化

先创建一个FutureTask对象,同样也是以匿名内部类形式创建的对象,然后将AsyncTask对象持有的mWorker传入到FutureTask的构造方法中,FutureTask对象负责持有一个Callable对象,在匿名内部类中重写了done()方法(本身FutureTask的done()方法的默认实现是空的,这里做了重写),最终FutureTask对象由AsyncTask对象持有的mFuture负责持有

 

getMainHandler()方法分析

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

Looper类的静态方法getMainHandler(),用于获得主线程中的Handler对象

1、首先线程需要持有AsyncTask类的Class对象锁

2、检查AsyncTask类还有的静态变量sHandler是否已经指向一个Handler对象

当AsyncTask类持有的Handler对象没有创建时,通过new一个InternalHandler对象,该对象是主线程的Looper对象

3、向调用者返回主线程的Handler对象

最后return自定义的Handler对象sHandler

 

InternalHandler构造方法分析

        public InternalHandler(Looper looper) {
            super(looper);
        }

位于AsyncTask类中,InternalHandler是一个静态内部类,它继承了Handler

 

call方法分析

            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()方法

1、mTaskInvoked是AsyncTask对象持有的一个AtomicBoolean对象,AtomicBoolean对象持有的boolean值,会保证在多个线程下安全更新,单个共享变量使用原子类是非常好的,这里首先将mTaskInvoked持有的boolean值赋值为true。

2、定义了一个局部变量result,看看后面要用它做什么?

3、Process.setThreadPriority方法则会设置线程的优先级,本处传入的优先级是Process.THREAD_PRIORITY_BACKGROUND,它的优先级值是10,目的就是让执行call方法的线程优先级较低,保障UI线程的顺利执行

4、这个call方法一定在工作线程中执行,它的内部调用了doInBackground方法(见6号知识点),传入的是WorkerRunnable对象持有的Params数组类(参数类型)的一个对象mParams。这条语句说明我们每次必须重写的doInBackground方法一定是在工作线程中执行的,它的返回结果将会由局部变量result负责持有

5、Binder.flushPendingCommands(),这是一个native方法,没明白具体的作用是什么?

6、上面执行语句中,出现的任何异常对象,都会捕获到(这里捕获的是Throwable),然后调用的是mCancelled的set方法,传入的值是true,mCancelled是AsyncTask对象持有的一个AtomicBoolean对象,这里是为了线程安全的更新AtomicBoolean对象持有的boolean值

7、一定会执行的finally代码块中,则调用了一个postResult方法(见7号知识点),并将局部变量result传了进去,result变量代表的是执行结果

8、最终方法返回的是result(参数类型为Result)

 

done()方法分析

            @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、最先调用的是一个get方法,它是FutureTask中的一个方法

2、接着是postResultIfNotInvoked方法的调用

3、捕获InterruptedException、以及ExcutionException,分别进行处理

一个是在标准输出流中打印日志,另一个是抛出RuntimeException对

4、捕获CancllationException对象,进行处理

通过调用postResultIfNotInvoked()方法进行处理,传入的参数为null

 

doInBackground()方法分析

 

    protected abstract Result doInBackground(Params... params);

在AsyncTask中定义的抽象方法,典型的模版方法模式的应用,供开发者重新用的,这个方法将在工作线程中执行

 

postResult()方法分析

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

1、首先通过getHandler方法(见8号知识点),获得一个Handler对象,接着调用Handler对象的obtainMessage方法,为其传入两个参数,一个是MESSAGE_POST_RESULT(常量值:0x1),另一个参数是AsyncTaskResult对象,它持有了当前的AsyncTask对象,和参数类型为Result的对象,obtainMessage方法返回的Message对象由局部变量message负责持有

2、接着为局部变量message调用一个sendToTarget方法,它会将Message对象通过Handler对象的sendMessage方法发送到MessageQueue中

3、最后返回的是Result对象

 

getHandler()方法分析

    private Handler getHandler() {
        return mHandler;
    }

返回的是AsyncTask持有的mHandler,它是与主线程相关的Handler对象

 

get()方法分析

    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

注意:它属于FutureTask类中的一个方法

 

总结

1、AsyncTask是抽象类,无法直接创建对象,由子类创建对象

2、AsyncTask对象必须在主线程中创建,因为AsyncTask类持有的Handler对象必须是主线程中的,这样才能做到线程间的通信

3、我们在堆中创建的每个AsyncTask对象持有的mHandler指向的都是AsyncTask类持有的sHandler对象

4、InternalHandler是AsyncTask中定义的静态内部类,它是扩展了Handler类的子类

5、WorkerRunnable是AsyncTask中定义的静态内部抽象类,它实现了Callable接口

6、AsyncTask是一个范型类,有三个参数类型,<Params, Progress, Result>

7、AsyncTaskResult是AsyncTask中定义的静态内部类,AsyncTaskResult对象负责持有当前AsyncTask对象和一个参数类型为Result的对象

在AsyncTask对象创建前,AsyncTask类加载时做了很多的工作,请参见第一篇文章:加载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值