Handler的工作原理。为什么在子线程中使用Handler会抛
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就好了