Android Handler消息机制详解9

819 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

d.为何主线程可以new Handler?如果在子线程new Handler需要做什么工作?

      因为主线程一启动的时候,在main()函数中,由系统已经帮我们完成了,我们主线程中的所有代码,全都运行在这两个函数(prepare() 和 loop())之间。

      所有的线程在使用Handler时都必须要prepare()和loop(),如果子线程中想要进行Handler操作,就必须在子线程中执行prepare() 和 loop();

      Looper.prepare(); Handler handler = new Handler();Looper.loop();

      子线程如果没有消息处理时,则需要执行Looper.quitSafely();主线程不允许quit(),执行quit方法时会抛异常。

e.子线程维护的Looper,消息队列无消息时的处理方案是什么?有什么用?

      当消息队列无消息时,loop()会block在Message msg = queue.next();

      调用Looper.quitSafely()方法,在Handle机制里面有一个Looper,在Looper机制里面有一个函数,叫做quitSafely()和quit()函数。

      这两个函数是调用的MessageQueue的quit()方法,执行nativeWake(mPtr),唤醒MessageQueue的next()里面的nativePollOnce(),最终返回message为null,loop()方法在判断message为null后会return,退出loop()。

      1.remove消息,把消息队列中的全部消息给干掉,也就释放了内存;达成了第一个作用:释放内存

      2.Looper结束(跳出死循环),则达成了第二个作用:释放线程

f.既然可以存在多个Handler往MessageQueue中添加数据(发消息时各个Handler可能处于不同的线程),那么它内部是如何确保线程安全的?

      synchronized()

g.使用Message时应该如何创建它?

      通过Message.obtain()来创建Message ;

      Message会维护一个大小为50的sPool,每次释放message时,只是把内容置空;有新消息创建时,从sPool里面取出head位置的message,然后初始化即可;

      内存复用,防止内存抖动(不断的创建,释放)

      享元设计模式

h.Looper死循环为什么不会导致应用卡死?

      卡死:是anr,输入事件在指定的时间内没有响应。

      loop():是睡眠,没有消息处理时,会block在Message msg = queue.next(),当有消息触发时,会唤醒执行 ;

      Looper.loop不断的接收处理事件,每一个点击触摸或者Activity每一个生命周期都是在Looper.loop()的控制之下进行的。

i.消息屏障和异步消息

      上面分析到,消息有三种类型普通消息、同步屏障消息和异步消息;因为消息处理有轻重缓急,就诞生了同步屏障消息和异步消息。它们俩是配套使用的,当消息队列中同时存在这三种消息时,如果碰到了同步屏障消息,那么会优先执行异步消息;比如:ViewRootImpl中的scheduleTraverals()中会先发送屏障消息,然后通过Choreographer发送异步消息来确保UI绘制优先执行。

j.IdleHandler

      IdleHandler是一个接口,里面有queueIdle()方法,从字面意思来看是空闲的Handler,通过MessageQueue中的addIdleHandler()执行,在前面的分析MessageQueue的next()方法中,如果消息队列中没到消息执行时间或没有消息时,会循环处理IdleHandler;适合场景:1.延迟执行,没有确切的时间;2.批量任务,任务密集,且只关注最终结果;

      以上就是对Handler消息机制的详细介绍及常见的问题,后续有新的收获会继续更新!