性能优化Android进阶之路Android技术知识

Handler---4部曲 --- 1. 总体流程

2021-11-06  本文已影响0人  liys_android

Handler---4部曲---1. 总体流程
Handler---4部曲---2. ThreadLocal 存储主流程
Handler---4部曲---3. MessageQueue队列
Handler---4部曲---4.细节补充

为什么分4篇呢?
因为我在看别人的博客中发现,人集中注意力的时间是有限的, 看太长时间容易累, 无法集中注意力,Handler的内容还是有点东西的.

Handler整体流程图.png
一 . ActivityThread中的main方法
public static void main(String[] args) {
        Looper.prepareMainLooper();
        Looper.loop();
}

总结: App启动, 执行2个方法.

1. Looper.prepareMainLooper()分析

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    //Looper.java
    @Deprecated
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) { //重复创建抛异常
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) { //重复创建抛异常
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //创建Looper对象, 保存到sThreadLocal中
        sThreadLocal.set(new Looper(quitAllowed));
    }

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
    }

总结:
1. 创建Looper对象(每个线程只有一个), 保存到sThreadLocal中
2. 创建队列mQueue = new MessageQueue(...) , mQueue是Looper对象的成员变量

Looper.loop() 分析

   public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

public static void loop() {
         // 1.从sThreadLocal中, 获取的Looper对象
        Looper me = myLooper(); 
        // 2.从Looper中, 获取队列
        MessageQueue queue = me.mQueue;
        for (;;) {
            //循环取出消息
            Message msg = queue.next();
            //处理消息
            msg.target.dispatchMessage(msg);
            //释放资源
            msg.recycleUnchecked(); 
       }
}

总结:sThreadLocal--->取出当前线程Looper对象--->取出队列, 循环从队列取出消息处理

二. Handler发送消息

new Handler()
    public Handler(xxx) {
          mLooper = Looper.myLooper();
          mQueue = mLooper.mQueue;
    }

总结:从Looper中取出队列, Handler中的mQueue 就是 Looper中的队列

handler.post(xxx), handler.sendXxx(...)
    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        enqueueMessage(queue, msg, uptimeMillis);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg,
            long uptimeMillis) {
        msg.target = this; //带着当前的Handler.
        return queue.enqueueMessage(msg, uptimeMillis);
}

总结: msg携带当前的Handler对象, 加到队列中.

总体流程完结

细节1:Main函数,不允许再次初始化.

Looer.prepareMainLooper.png

细节2:每个线程只允许prepare()初始化一次

Looper.prepare().png
上一篇下一篇

猜你喜欢

热点阅读