美文网首页
Handler的工作原理。为什么在子线程中使用Handler会抛

Handler的工作原理。为什么在子线程中使用Handler会抛

作者: 杨殿生 | 来源:发表于2018-08-16 19:16 被阅读0次

    Handler是做什么的?

    Handler了它在安卓中常见的工作就是子线程与主线程的通信,其实可以直接归类为线程和线程间的通信

    Handler工作原理是什么?

    谈到Handler会涉及到以下几个类
    Handler、Message、Looper、MessageQueue
    我们一个一个来说,首先设置场景在一个线程中通知另一个线程

    首先我们需要创建一个Looper它用于去轮询MessageQueue,如果MessageQueue里面有Message,那么使用Handler去处理Message

    1,创建Looper和创建MessageQueue
    首先在一个线程里要用Handler,那么需要准备Looper,调用Looper.prepare(),我们在主线程里面不用准备Looper,那么是因为在我们的主线程中已经给我们初始化好了Looper,
    在准备Looper的时候会去校验这个线程中是否存在Looper,如果有Looper那么抛出异常(注意:有一些面试官会问如何判断一个线程中是否存在一个Looper的,它用的是ThreadLocal,它的作用是在线程范围内保证变量的唯一性,Thread中会维护一个类似HashMap的东西,然后用ThreadLocal对象作为key,value就是要存储的变量值,这样就保证了存储数据的唯一性)
    如果没有Looper那么new一个Looper,new Looper的同时会new 一个MessageQueue(注意:一个线程中只有一个Looper一个MessageQueue)
    然后Looper.loop()就可以启动轮训来轮训消息队列了
    2,创建Handler
    这个我们在熟悉不过了,继承一个Handler然后复写handlerMessage方法,这里其实面试官也可以问一些比较细致的问题,如下

    创建Handler会引起内存泄露,如何避免?
    内部泄露的原因:Java中非静态内部类会默认持有外部类的引用,如果你创建的Handler没有使用静态内部类那么他会持有外部Activity或者Fragment的对象,如过你Activity finish掉了,Handler还在Message队列中没有被处理还会持有Activity引用那就会内存泄露,怎么解决两种方式
    1,使用静态内部类,静态内部类不持有外部类的应引用所以没事
    2,使用软引用或者弱引用

    注意:有面试官会问可以创建几个Handler,我负责任的说是多个,哪个Handler发送的消息哪个Handler处理(吐槽一下有的面试官,你自己把自己要问的问题搞清楚了在去问别人,非要跟我犟只能创建一个)

    3,创建Message
    Message一般都是使用Message.obtain(),它这里面是有一个spool指向一个Message对象,还有一个next指向下一个Message,它里面维护了一个链表,obtain的时候在表头头取Message,在Message回收的时候在表头添加一个Message,类似栈,默认大小是50
    4,消息的处理
    Handler对象sendMessage发送消息放入的MessageQueue队列中,Looper轮训到它,然后就开始处理Message,Message会有一个target去记录是哪个Handler发送的它,会调用这个Handler中的dispatchMessage()方法,如果说Message中实现了CallBack那么调用Message中的CallBack,如果Handler中实现了Callback调用Handler中CallBack,否则就都调动Handler中的handleMessage方法

    为什么在子线程中使用Handler会抛出异常?

    根据上面的原理分析,那就是因为你子线程中没有Looper,给他一个Looper就好了

    相关文章

      网友评论

          本文标题:Handler的工作原理。为什么在子线程中使用Handler会抛

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