Handler常见问题

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

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

public static void main(String[] args) {
    // 省略n行
    Looper.prepareMainLooper();
    // 省略n行
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    // 省略n行
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

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

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

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

// Handler.java
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
// Looper.java
public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;
    // 省略n行
    for (;;) {
        // 省略n行
        Message msg = queue.next(); // might block
        // 省略n行
        try {
            // 此处找到对应的handler进行消息分发
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        // 省略n行
        msg.recycleUnchecked();
    }
// 省略n行
}

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 会抛异常

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值