No1Worker / Q-A

0 stars 0 forks source link

Handler相关的问题整理 #3

Open zhiyongyu opened 4 years ago

zhiyongyu commented 4 years ago

A、messageQueue.next 是阻塞式的取消息, 如果有 delay 会调用 nativeWake; 那么问题来了, 线程挂起了, 是挂起的 UI线程吗? 答案是 YES, 为什么我没有察觉呢? 还有就是 nativeWake 和 nativePollOnce 的实现原理; B、looper.loop 既然是 while-true 为什么不会卡死? C、MessageQueue 是队列吗? 他是什么数据结构呢? D、handler 的postDelay, 时间准吗? 答案是不准, 为什么呢? E、handler 的 postDelay 的时间是 system.currentTime 吗? 答案是 NO, 你知道是什么吗? F、子线程run方法使用 handler 要先 looper.prepare(); 再 handler.post; 再 looper.loop(); G、handler 这么做到的 一个线程对应一个 looper, 答案是threadLocal, 你对ThreadLocal 有什么了解 吗? H、假设先 postDelay 10ms, 再postDelay 1ms, 你简单描述一下, 怎么处理这2条消息? I、你知道主线程的Looper, 第一次被调用loop方法, 在什么时候吗? 哪一个类 J、你对 IdleHandler 有多少了解? K、你了解 HandlerThread 吗? L、你对 Message.obtain() 了解吗, 或者你知道 怎么维护消息池吗

zhiyongyu commented 4 years ago

A: 线程是挂起了,为什么没有察觉是因为有nativeWake会唤醒他,主线程也是随时在挂起,阻塞的。 主线程接收的不光是我们发送的消息,还有系统的,比如安卓屏幕16.6ms刷新一次,就会不停的去唤醒这个主线程,当然还有其他的一些,比如输入法啊,系统广播啊等等这些。 所以在我们看来,界面是没有阻塞的。 TODO:nativeWake 和 nativePollOnce 的实现原理

zhiyongyu commented 4 years ago

B: 因为在ActivityThread的main方法中,启动了一个新的Binder线程(即ApplicationThread)用于接收系统服务发来的事件。 一些 Activity 生命周期的消息就是通过这个机制在循环外执行起来的。 比如一条暂停 Activity 的消息,首先是处于系统 system_server 进程的ActivityManagerService(AMS)线程调用 ApplicationThreadProxy(ATP)线程, 接着 ATP 线程通过 Binder 机制将消息传输到 APP 进程中的 ApplicationThread(AT)线程, 最后 AT 线程通过 Handler 消息机制,将消息发送到了主线程的消息队列中,主线程通过Looper.loop() 遍历得到该消息后,将消息分发给了 ActivityThread 对应的 Handler 中处理, 最后调用到了 Activity 的 onPause() 方法,方法处理完后,继续主线程继续循环下去。

zhiyongyu commented 4 years ago

C: MessageQueue不是队列,它内部使用一个Message链表实现消息的存和取。

zhiyongyu commented 4 years ago

D: 因为postDelay使用了SystemClock.uptimeMillis(),在手机进入休眠之后,将不会计时,比如设置的延时时间是500。但是在过了100之后手机进入休眠了,过了200之后重新退出休眠,那么实际上handler收到消息的时间是合计经过了700。延伸问题:如何解决这种问题?