Handler是一个优秀的内存共享方案。其内存管理和设计思路相当完整。 通过Handler来通知UI组件更新或者是处理对应消息。那么具体Handler机制是什么?

Handler1 Looper

开篇问题

1.一个线程有几个handler

2.一个线程有几个looper,如何保证

3.Handler会出现内存泄漏问题吗,怎么解决内存泄漏

4.子线程总如何使用Handler

Handler整体流程

优先级队列

Handler流程图

Looper

ThreadLocal

ThreadLocalMap

1.looper。java中无限调用queue。next,会不会出现msg=null

messagequeue。java

nativePollOnce(),linux层休眠

image-20210801172227096

一个线程有几个handler

一个,ui主线程中可以有activty,service,他们都可以使用UI主线程

一个线程有几个looper,如何保证

looper。java中prepare函数如果存在threadlocal那么会抛出异常不能new looper,所以一个threadlocal对应一个looper

handler内存泄漏原因

内部类持有外部类引用。this调用ondestory并不能释放,jvm认为当前this正在被handler使用,内部类没办法释放,this类也没办法释放

(其他内部类是不耗时的)

handler原理

其他的类不存在内存泄漏。

handler可以发送delay

image-20210801193344885

handler中msg。target=this

messagequeue会持有message,msg中持有了一个handler,handler中持有了this,

怎么解决内存泄漏

软引用加static,百度

子线程创建handler如何解决?

主线程为什么可以new handler?

looper初始化prepare

其中activitythread。java中main函数Looper。prepareMainLooper(),Looper。loop()

子线程使用handler,looper必须prepare然后再Loop,才能使用handler

ams是以activitythread

子线程维护一个Looper,消息队列无消息的时候处理方案是什么,有什么作用

Looper。prepare,new handler,Looper.loop,Loop。quitSafely

在Looper。loop中有一个for(;;)死循环中Message msg=queue。next(),使得Looper一直阻塞不会退出

Looper里面有一个quitSafely()调用messagequeue quit函数中有mQuitting=true,removeAllFutureMessageLocked释放内存,nativeWake会通知Message next()函数中nativePollOnce(),让他取消阻塞执行下去。

其中,messagequeue这个类里面的Message next()里面也是死循环,一旦执行下去之后发现mQuiiting为true,return null

也就是Looper。loop中的死循环

if (msg == null) return;loop收到null直接返回

quitSafely作用,

1.释放内存,获取不到Looper。且让Looper退出

2.释放线程

主线程使用Loop。quitSafely,会抛出异常不让你调用

销毁的过程只是置零,并不会把东西一个一个移除

子线程-》主线程

保证不会出现队列的混乱,保证线程安全

涉及了多线程并发编程

1.安全性

Messagequeue里面的enqueueMessage放消息里面有synchronize

next取消息synchronize,保证取消息

2.handler delay消失时间准确吗?安全性

synchronize修饰一个方法,静态方法,代码块(object)和代码块(this)区别

我们使用message该怎么创建

obtain

内存共享,内存复用,内存抖动

享元设计模式

synchronize(spoolsync)

Message m=spool

Message属性会持有一个next,spool是消息队列的头,属于链表

使用handler delay消息队列会有什么变化

这个消息队列为空,不会立刻执行,计算等待时间

添加一个message,立刻在messagequeue里面的enquemessage函数nativeWake来唤醒Message next()函数中nativePollOnce(),接着出发Message next()函数中nextPollTimeoutMills变量的值,等下次next循环会在nativePollOnce中体现睡眠时间,wait

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

主线程泡在Looper。loop

app都有一个虚拟机,都有一个main函数

(ams问题APP启动流程)launcher-》application-》zygote-》虚拟机-》ActivityThread

activity,service都有一个loop 以消息的方式存在

主线程唤醒的方式

1)输入事件2)往looper里面添加消息

ANR(屏幕按下)广播10秒内没有执行

主线程中Looper。loop next会休眠

类似微信banner,消息都会第二天通知,ui主线程休眠

应用卡死跟Looper是没有关系的,应用卡死是跟输入无响应有关

1.Looper。loop中的queue。next是在休眠,并不是卡死(ANR)

2.屏幕上的操作即为输入事件,输入完之后

msg。target。dispatchMessage

问题回答

参考

猜你想看

Handler2 Thread

Handler3 同步屏障

Handler4 HandlerThread

Handler5 IntentService