• Handler常见问题


    1. 主线程的Looper是什么时候创建的?

    frameworks/base/core/java/android/app/ActivityThread.java 中的main函数

    1. public static void main(String[] args) {
    2. // 省略n行
    3. Looper.prepareMainLooper();
    4. // 省略n行
    5. ActivityThread thread = new ActivityThread();
    6. thread.attach(false);
    7. if (sMainThreadHandler == null) {
    8. sMainThreadHandler = thread.getHandler();
    9. }
    10. // 省略n行
    11. Looper.loop();
    12. throw new RuntimeException("Main thread loop unexpectedly exited");
    13. }

    2. 即然用的是同一个队列,那怎么区分消息是由哪个handler接收呢?

    发前消息时会将当前的Handler放到msg.target中.

    当loop有收到新消息时调用msg.target.dispatchMsg将消息分发到对应的loop

    1. // Handler.java
    2. private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    3. msg.target = this;
    4. if (mAsynchronous) {
    5. msg.setAsynchronous(true);
    6. }
    7. return queue.enqueueMessage(msg, uptimeMillis);
    8. }
    9. // Looper.java
    10. public static void loop() {
    11. final Looper me = myLooper();
    12. if (me == null) {
    13. throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    14. }
    15. final MessageQueue queue = me.mQueue;
    16. // 省略n行
    17. for (;;) {
    18. // 省略n行
    19. Message msg = queue.next(); // might block
    20. // 省略n行
    21. try {
    22. // 此处找到对应的handler进行消息分发
    23. msg.target.dispatchMessage(msg);
    24. } finally {
    25. if (traceTag != 0) {
    26. Trace.traceEnd(traceTag);
    27. }
    28. }
    29. // 省略n行
    30. msg.recycleUnchecked();
    31. }
    32. // 省略n行
    33. }

    3. 如何保证线程安全

    往队列放或着获取msg时会用synchonize同步,保证安全

    4. postDelay是怎么实现的?

    andorid.os.MessgeQueue.java 队列会根据delay进行排队, 会调用nativenativePollOnce(ptr, nextPollTimeoutMillis) 进行等待.

    放消息队列enqueMessage时会, 同时会调用nativeWait(ptr) 重新计算时间nextPollTimeoutMillis 重新调用nativenativePollOnce进行等待

    5. handler内存泄露?

    内部类持用外部类的对象, 当handleMessage持有activity时

    message.target会持用Handler,Handler会持有用外部类

    外部类生成的对象被message并放到messageQueue引用。

    messageQueye=>message=>handler=>Activity

    可以用软引用解决

    6.loop线程如何退出?

    message.quit() 会设置mQuiting= true, removeAllMessage nativeWait。

    7. MailLoop调用quit会怎样?

    主线程mQuitAllowed=false 会抛异常

    1. if (!mQuitAllowed) {
    2. throw new IllegalStateException("Main thread not allowed to quit.");
    3. }

    8. Loop.quit()和Loop.quitSafely区别?

    quit()实际上是把消息队列全部清空,然后让MessageQueue.next()返回null令Looper.loop()循环结束从而终止Handler机制,但是存在着不安全的地方是可能有些消息在消息队列没来得及处理。

    而quitsafely()做了优化,只清除消息队列中延迟信息,等待消息队列剩余信息处理完之后再终止Looper循环。

    简单理解已到时间的消息会继续执行,延时消息直接清空

  • 相关阅读:
    GAN的原理与应用PPT
    能力提高篇--协调能力【对接】
    MATLAB算法实战应用案例精讲-【目标检测】机器视觉-工业相机
    3.10、以太网交换机的生成树协议 STP
    acwing算法提高之数据结构--并查集
    JAVA中的垃圾回收器(1)
    《软件工程与计算》期末考试真题范例及答案
    Wifi列表扫描和Wifi链接
    华为 2024 届实习校园招聘-硬件通⽤(大部分硬件技术工程师岗位适用)/单板开发——第四套
    ES6的内置对象扩展
  • 原文地址:https://blog.csdn.net/logocool/article/details/126785464