美文网首页面试篇源码篇
系统Handler源码分析

系统Handler源码分析

作者: MrWang915 | 来源:发表于2017-05-04 18:01 被阅读9次

    参考 http://www.jianshu.com/p/ac50ba6ba3a2

              http://www.jianshu.com/p/aa6b6152217d

    几个要点

    消息其中包括:

         我们自己的操作消息(客户端的 Handler)

          系统的操作消息(系统 Handler):比如启动 Activity 等四大组件(例如       突然来电话的时候跳转到电话界面)

    线程不安全问题归根结底主要涉及到变量的多线程访问问题,例如变量的临界问题、值错误、并发问题等

    1 系统的handler类名为大写的H (继承Handler)

    2 为ActivityThread 的成员变量,在 new ActivityThread 的时候,系统的 Handler 就初始

    3 在 main 方法里面,然后创建了 Looper,然后开启消息循环。之所以我们的APP能够一直运行着,就是因为 Looper.loop() 里面是一个死循环:

    public static void loop() {

       for(;;) {    }

    }

    4 在非主线程里面我们也可以搞一个 Handler,但是需要我们主动去为当前的子线程绑定一个 Looper,并且启动消息循环。

    5 post方法(封装了带Runnable的Message) 最终都是调用sendMessageAtTime方法,把消息放到消息队列里面:

    6 消息并不是一直在队列的尾部添加的,而是可以指定时间,如果是立马需要执行的消息,就会插到队列的头部,就会立马处理,如此类推。

    7 ThreadLocal 是JDK提供的一个解决线程不安全的类,线程不安全问题归根结底主要涉及到变量的多线程访问问题,例如变量的临界问题、值错误、并发问题等。这里利用ThreadLocal 绑定了 Looper 以及线程,就可以避免其他线程去访问当前线程的 Looper 了。

    8  Looper 与线程的关联是通过 ThreadLocal 来进行的

    9  MessageQueue 是Looper对象的成员变量 (消息队列是通过链表实现 指向下一个结点)

    Looper与当前线程绑定

    调用prepare(prepareMainLooper())方法来关联线程和Looper  //sThreadLocal.set(newLooper(quitAllowed));

    Looper的成员变量sThreadLocal

    static final ThreadLocal sThreadLocal =newThreadLocal();

    在prepare方法中new了一个Looper并且设置到sThreadLocal里面sThreadLocal.set(newLooper(quitAllowed));

    消息池的概念

    1 Message Pool消息池的概念——重复利用Message (利用享元模式去循环利用)

    2 通过obtain方法取出一条消息的时候,如果发现当前的消息池不为空,那就直接重复利用Message(已经被创建过和handle过的);如果为空就重新 new 一个消息。这就是一种享元设计模式的概念

    3 消息的去取出并不是直接就从队列的头部取出的,而是根据了消息的when时间参数有关的,因为我们可以发送延时消息、也可以发送一个指定时间点的消息

    迭代消息过程

    1 首先拿到Looper对象(me),如果当前的线程没有Looper,那么就会抛出异常,这就是为什么在子线程里面创建Handler如果不手动创建和启动Looper会报错的原因。

    2 Looper的成员变量MessageQueue,在MessageQueue里面不断地去取消息

    for(;;) { 

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

    if(msg ==null) {

    // No message indicates that the message queue is quitting.

    return;

            }

    //处理消息

    try{ 

     msg.target.dispatchMessage(msg); 

      }

    finally{ }  

       } 

    msg.recycleUnchecked();//回收消息}

    Handler、Looper是怎么关联

    在初始化Handler类中

    public Handler(Callback callback, booleanasync){   

     mLooper = Looper.myLooper();//见下文备注 第二块核心代码

    //如果当前线程(子线程)没有Looper,就需要我们程序要去手动prepare以及启动loop方法了

    //子线程里面默认没有Looper循环器

    if(mLooper ==null) {

    thrownewRuntimeException("Can't create handler inside thread that has not called Looper.prepare()"); 

       }  

      mQueue = mLooper.mQueue; 

       mCallback = callback;  

      mAsynchronous =async;

    }

    第二块核心代码

    public static @Nullable Looper myLooper(){

    returns  ThreadLocal.get();//返回与当前线程绑定的Looper

    }

    相关文章

      网友评论

        本文标题:系统Handler源码分析

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