AsyncQueryHandler研究

    技术2022-05-19  28

    今天晚上研究了一下啊AsyncQueryHandler,收获挺大,记录下重要知识点,以后继续补充研究。

    研究AsyncQueryHandler这个类的时候遇到了几个重要的不清楚的知识点

    1. Handler与Thread,Looper的关系

    2. HandlerThread是干什么用的

    3. ThreadLocal类是干什么用的

    Handler主要是用来发送和处理消息,但是发送了消息后,消息是怎么传递的呢?这就是Looper的作用了,每个Handler中都会有一个Looper对象,如果在创建Handler的时候不指定,系统就会默认将当前线程的Looper绑定到Handler上,Looper对象中维护者一个消息队列,Hander发送的消息都会存储到这个消息队列中,Looper不断的遍历这个消息队列,取出消息,交给handleMessage方法处理。Looper属于哪个线程,hadleMessage方法就会在那个线程中执行。

    HandlerThread不但能提供异步处理,Handler处理消息的方法也会在这个线程中执行,他最要的作用就是提供了一个线程。(这个类还有待研究)

    ThreadLocal类主要是用来多个模块共享变量用的,但是不同线程之间的变量的值却不相同。

    说明1:对象a,对象b比如说是某个类的实例对象,在模块A,B,C中共享对象a,还有对象b,在线程A中,模块A中设置a的值,在模块B,C中取出a的值,三个模块操作的是同一个值,但是对象a和对象b分别属于两个线程,他们是不同的。

    AsyncQueryHandler的工作机制是什么?

    AsyncQueryHandler继承了Handler对象,但是他提供的构造方法中却没有Looper参数,也就是说他和他所在的当前线程绑定,AsyncQueryHandler内部有一个Hhandler对象,叫mWorkerHandler,他和一个HandlerThread绑定,mWorkerHandler负责将打包好的消息发送,并且处理,并将结果作为消息发送给AsyncQueryHandler。他是怎么发送的?AsyncQueryHandler内部有一个WorkerArgs完美类,他封装了startAsyncQuery等方法的参数,并且通过这行代码

    WorkerArgs args = new WorkerArgs();        args.handler = this;

    将当前Handler封装进去,发送到HandlerThread中去,mWorkerHandler处理完消息得到结果后,args.handler将结构发送给自己进行处理。(这就是线程间的通信了)

    mWorkerHandler和一个子线程绑定,能够处理比较耗时的操作,AsyncQueryHandler提供异步处理。

     

    总结:

    Handler有两个作用,Handler用在一个线程中,就是实现异步操作。用在不同的线程之间,那就是异步操作加线程间通信。

    补充:

    HandlerThread:

    先看他的类描述:Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

    这是一个包含了Looper对象的线程,这个looper可以用来创建Handler对象,记住:start()方法必须被调用,否则通过getLooper方法得到的looper对象是空的。通过调用start方法,就会去执行该线程的run方法, public void run() {

            mTid = Process.myTid();

            Looper.prepare();//创建一个Looper实例,并且存储在ThreadLocal中,ThreadLocal中维护一个HashMap,键是线程号

            synchronized (this) {

                mLooper = Looper.myLooper();//得到当前线程的Looper,就是刚才perpare方法中创建并存储的那个Looper实例

                Process.setThreadPriority(mPriority);

                notifyAll();

            }

            onLooperPrepared();

            Looper.loop();//开始轮询

            mTid = -1;

        }

     

     public static final void prepare() {

            if (sThreadLocal.get() != null) {

                throw new RuntimeException("Only one Looper may be created per thread");

            }

            sThreadLocal.set(new Looper());

        }

     

     public static final Looper myLooper() {

            return (Looper)sThreadLocal.get();

        }

     

     

    AsyncQueryHandler是如何提供onxxxComplete方法给用户,由用户自己实现的?

    public abstract class AsyncQueryHandler extends Handler  他是一个抽象类

     

    MessageQueue是不是一个任务队列?

    是,他是一个优先级队列(可以通过ArrayList的排序来实现)。它内部自己维护一个ArrayLsit集合,用来存储Message消息,Message消息有三种,普通消息,按照先发送先执行的FIFO原则进行;高优先级的消息,这种消息会直接插在队列的最前面,立刻执行;还有一种定时消息,类似于定时任务,到时间才执行。

    Looper是如何轮询MessageQueue的?

    当在主线程中使用Handler的时候,不用指定Looper,因为在主线程开启的时候,就已经调用了Looper.loop()方法开始轮询了。

    挡在子线程中使用Handler的时候,通过调用Looper的prepare方法创建存储Looper对象,还得调用Looper.loop()方法开启轮询。

    当配合HandlerThread使用Handler的时候,HandlerThread的run方法中调用了Looper.loop()方法。

     

        public static final void loop() {

            Looper me = myLooper();

            MessageQueue queue = me.mQueue;

            while (true) {

                Message msg = queue.next(); // might block

                //if (!me.mRun) {

                //    break;

                //}

                if (msg != null) {

                    if (msg.target == null) {

                        // No target is a magic identifier for the quit message.

                        return;

                    }

                    msg.target.dispatchMessage(msg);

                    msg.recycle();

                }

            }

        }

    Message消息实现了Parcelable接口


    最新回复(0)