Android 基础技术——Handler

笔者希望做一个系列,整理 Android 基础技术,本章是关于 Handler
为什么一个线程对应一个Looper?

核心:通过ThreadLocal保证

Looper.prepare的时候,ThreadLocal.get如果不空报异常;否则调用ThreadLocal.set, ThreadLocal.set 会调用当前线程Thread里的ThreadLocalmap  put 键值对,put 的键值对就是 Key = ThreadLocal, Value = Looper

线程里有TreadLocalMap的成员变量  Key = ThreadLocal,  Value = Looper   

Looper 中有一个 static final 的成员变量就是 ThreadLocal,意味着唯一性

 Looper有final的成员MessageQueue

Android 基础技术——Handler_第1张图片

一个线程可以有多少个 Handler?

可以有多个

Handler内存泄漏的原因

匿名内部类handler 默认持有外部类的activity的引用。

并且Handler.enqueMessage的时候, msg.target = handler, message持有了handler,

引用链:msg->handler->activity或者fragment

为什么主线程可以New handler; 子线程new handler需要做什么

子线程 必须 Looper.prepare + Looper.loop

主线程   在ActivityThread.main方法里  帮你Looper.prepareMainLoop和Looper.loop

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

主线程会阻塞,主线程不能调用quit

子线程没有消息的时候,需要调用quit 

这个quit作用:唤醒线程;

调用 quit 后,messagequeue返回null 退出loop

消息的睡眠的唤醒机制是怎样的?

生产者消费者模式

入队满的时候  阻塞    这个handler没有限制满的情况

出队空的时候 阻塞

java的多线程里有阻塞队列,但是handler不是这样,没有限制消息个数

nativePollOnce 到了C++层 会调用epoll_wait等待, 阻塞整个线程, CPU释放

nativeWake 到了C++层调用 epoll 的wake

多个handler往messagequeue发送消息 如何保证线程安全

通过两点来保证线程安全:

一个线程只有一个messageQueue

使用synchronized, 内置锁,加锁和释放是JVM帮我们完成的,锁的是MessageQueue 对象里面的所有函数/代码块都受限

子线程发送消息,为什么能在主线程接收,也就是线程是如何切换的

子线程thread: handler.sendMessage->MessageQueue.enqueMessage.

MessageQueue是没有线程之说。他是一个数据结构,内存共享

主线程loop   轮询MessageQueue。这个时候MessageQueue.next在主线程执行。

 ThreadLocal整个系统只有一个吗? 会不会有矛盾

线程1-ThreadLocalMap1  唯一的ThreadLocal-looper1

线程2-ThreadLocalMap2  唯一的ThreadLocal-looper2

一个线程对应一个Looper,一个Looper 对应一个 ThreadLocal

调整系统时间对延时消息有没影响

Handler的延迟消息计算是通过SystemClock类来计算,跟系统时间没有任何关系,这是根据Handler自启动以来非睡眠正常运行时间的毫秒数和代码指定的postDelayed的时间来计算的。

我们使用Message如何创建?

通过obtainMessage

享元设计模式: 内存复用,android中使用非常广泛  如recyclerView

维持一个消息池,防止内存碎片->内存抖动->OOM

消息释放后,插入到队列头部,重置队头为这个消息节点

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

和anr无关。

为什么msg 阻塞不会导致anr?  

这个阻塞是指线程没有事情做了,释放cpu,休眠

什么是同步屏障?

msg.target=null 的消息就是同步屏障

同步屏障的场景:刷新UI    ViewRootImpl   scheduleTraversals---> postSyncBarrier 在对头插入节点

同步屏障的删除:ViewRootImpl   unScheduleTraversals---->removeSyncBarrier  删除屏障的节点

同步屏障:就是把同步消息给屏障掉了!! 然后优先执行异步消息(setAsynchrious标志)

messageQueue.next的时候  

先判断 如果msg.target==null  轮询消息队列,直到找到一个异步消息为止,执行这个异步消息。

setAsynchrious(true)这个标志。

刷新UI 使用了同步屏障就是为了保证及时执行消息,如果保证不了16ms 刷新一次, 会导致掉帧。

我们平时发送到消息是同步消息

同步屏障的作用是什么??

我们向主线程发送了一个UI绘制操作Message,而此时消息队列中的消息非常多,那么这个Message的处理可能会得到延迟,绘制不及时造成界面卡顿。同步屏障机制的作用,是让这个绘制消息得以越过其他的消息,优先被执行。

你可能感兴趣的:(Android,基础技术,android,android,基础)