美文网首页
Android面试必问handler机制浅析

Android面试必问handler机制浅析

作者: 蜗牛是不是牛 | 来源:发表于2022-02-26 22:14 被阅读0次

    Handler机制

    1、Handler是什么

    Handler是Android中的异步消息处理机制。当发送一个消息之后,这个消息是进入一个消息队列(MessageQueue),在消息队列中通过Looper去循环的获取队列中的消息,然后将消息分派给对应的处理者进行处理。

    2、Handler四模块

    Message:存储需要处理操作的信息

    MessageQueue:先进先出,存储handler发送过来的消息

    Looper:循环器,它是消息队列和handler的通信媒介,1:循环的取出消息队列中的消息;2:将取出的消息发送给对应的处理者

    Handler:主线程和子线程的通信媒介,1:添加消息到消息队列; 2:处理循环器分派过来的消息

    3、Handler 死循环导致应用卡死?

    在handler机制中,Looper.loop方法会不断循环获取Message, 其中的消息的获取是通过调用MessageQueue的next()方法获取的,而该方法会调用nativePollOnce()方法 ,这是一个native方法。底层的实现涉及到Linux pipe/epoll机制,nativePollOnce()被阻塞时,主线程会释放CPU资源,进入休眠状态. 直到下个消息到达或者有事务发生,会通过pipe管道写端写入数据来唤醒looper工作。

    Android6.0及以前的版本使用管道与epoll来完成Looper的休眠与唤醒的

    Android6.0及以后的版本使用eventfd与epoll来完成Looper的休眠与唤醒的

    4、子线程中维护的Looper,如何终止消息循环?有什么用?

    如果不处理的话,会阻塞线程,处理方案是调用Looper的quit()(清空所有的延迟和非延迟的消息)和quitSafely()(只清空延迟消息); 这个方法会调用MessageQueue的quit()方法,清空所有的Message,并调用nativeWake()方法唤醒之前被阻塞的nativePollOnce(),使得方法next()方法中的for循环继续执行,接下来发现Message为null后就会结束循环,Looper结束。如此便可以释放内存和线程

    5、Handler为何使用管道?

    同进程线程间内存共享,通过handler通信,消息的内容是不需要从一个线程拷贝到另一个线程,因为两个线程间可使用的内存是同一个区域。(注意:线程私有区域ThreadLocal)

    管道的作用就是当一个线程准备好Message,并放入消息池,这时需要通知了一个线程B去处理这个消息。线程A向管道的写端写入数据,管道有数据便会唤醒线程B去处理消息。管道的作用是用于通知另一个线程的,这便是最核心的作用。

    image

    6、Handler为何使用管道而非binder

    从内存角度,通信过程中binder涉及到一次内存拷贝,handler机制中的Message根本不需要拷贝,本身就是在同一片内存。

    从CPU角度,为了Binder通信底层驱动还需要创建一个binder线程池,每次通信涉及binder线程的创建和内存的分配等比较浪费CPU资源

    7、handler导致内存泄漏的原因

    原因:handler发送的消息在当前handler的消息队列中,如果此时activity被finish掉了,那么消息队列的消息依旧由handler进行处理,若此时handler申明为内存类(非静态内部类),内部类持有外部类的实例引用,这样在GC垃圾回收时发现Activity还有其他引用存在,因而就不会去回首这个Activity,进而导致Activity泄漏。

    方法:使用静态内部类,并且使用WeakReference包裹外部类的对象。首先静态内部类不持有外部类的引用,使用静态的handler不会导致activity的泄漏,handler定义static的同时,还要用WeakReference包裹外部类的对象。

    最后

    相关推荐

    相关文章

      网友评论

          本文标题:Android面试必问handler机制浅析

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