美文网首页
Handler机制原理和常见问题

Handler机制原理和常见问题

作者: 钱晓缺 | 来源:发表于2020-10-26 23:05 被阅读0次

    基本元素

    Handler

    用于处理消息,包括将发送消息到消息队列,和从消息队列中分发出去。

    Message

    用户对屏幕操作而产生的信息。

    Looper

    一个死循环,不停地轮询等待线程给它的消息。

    MessageQueue

    存放消息的队列,是一个优先级队列,当新插入一个消息的时候,会先和队列内的消息的执行时间做对比,然后插入,执行时间越短,优先级越高,具体方法在enqueueMeassage()方法中。

    工作流程

    首先可以把整个过程当成一个生产流水线,handler是机器手,message就是产品,messagequeue就是流水线的传输带,handler将message发送到传输带messagequeue上,message按照时间顺序排列在运输袋子上,looper就是发动机带动转轴,把message运输出去,最后又是handler把message分发出去。

    具体的方法过程如下:

    Handler首先调用sendMessage(),而sendMessage又调用MessageQueue的enqueueMessage()方法,该方法的目的是把message存在消息队列中。

    现在消息已经在消息队列中了,需要一个动力去让这些消息被挨个的处理,于是我们就需要looper中的loop函数,它会调用queue.next()方法,这就取到了一个队列中的message,然后handler继续调用dispatchMessage()方法,该方法就包含了handler的handleMessage()方法,然后就会循环该过程。

    常见问题

    1.Looper如何停下来

    当消息队列是空的时候,loop执行queue.next()的时候会阻塞,此时就可以停下来。

    2.一个线程中几个handler

    随便多少个,new一个有一个。

    3.一个线程有几个looper

    一个,由threadlocal决定。一个线程里面有一个threadlocalMap类型的变量,里面保存的是threadlocal,所以threadlocal是个key,value键值对,Looper的构造函数是个私有函数,只有在prepare()方法中初始化,在该方法中,set方法会获取当前线程,获取当前threadlocalMap,一个线程只对应一个map,map中一个key对应一个value,key是threadlocal,value就是Looper,所以一个线程绑定一个looper。

    4.Handler为什么会内存泄漏,解决方案

    Handler持有Activity。因为handler是个匿名内部类,可以持有外部类对象,所以handler持有activity。内存泄漏和handler的机制有关,message持有handler,handler又持有activity,message又有延迟处理的情况,所以会一直存在消息队列中,这时候messageQueue又持有activity,只要message不及时处理,activity就不会被回收。解决方案是:activity弱引用。

    5.为什么在主线程中可以直接new handler

    当启动app的时候,会先启动Luncher,然后在linux层,会调用zygote去给每个应用建立一个虚拟机,此时会调用activityThread再去使用main方法,里面就有prepareMainLooper方法,此时可以知道所有组件都是围绕主线程looper,以消息存在。

    6.怎么在子线程中new一个handler

    先Looper.prepare(),在new handler,最后Looper.loop()

    7.子消息Looper,没有消息怎么办

    消息队列没有消息,会调用nativePollOnce方法,这个方法会进去等待状态,此时会调用linux的epoll函数并传入-1,epoll函数会将结果传入linux的消息队列中,若这个值是-1,则会陷入永久等待状态,线程挂起。

    8. Looper怎么退出

    调用messageQueue.quit方法,这个过程中,首先removeAllmessageLocked(),把所有的消息全部移出去。此时调用了recycleUnchecked()方法,将消息内部变量赋值为null,然后调用nativeWake(),这个和epoll相反,它唤醒了线程,并返回一个为null的msg,Loop中for循环就会终止。

    9.主线程需要释放looper吗

    不能,AMS围绕handler管理,四大组件也是靠主线程的Looper处理操作

    10.多个handler往消息队列放消息怎么保证线程安全

    加锁,使用synchronized

    11.怎么生成一个message

    使用享元设计模式,提前已经存在了一个消息队列,已经处理完的消息,会被赋值为null,并且用头插法存在这个列表中。当使用obtain的时候会从该消息队列中获取一个空消息

    12.Looper为何不会让应用卡死

    二者之间,ANR的原因是消息没有被及时处理,而looper没有消息时候会进入睡眠状态释放线程。

    相关文章

      网友评论

          本文标题:Handler机制原理和常见问题

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