字节跳动技术整理:进程间的通信-之-Handler机制,社招面试心得

本文详细介绍了Android中Handler机制的工作流程,包括如何在工作线程中发送消息到消息队列,以及使用Handler.post()的方式。同时,分析了内存泄露问题,特别是非静态内部类Handler导致的内存泄露原因,并提供了两种解决方案:静态内部类+弱引用,以及在外部类结束生命周期时清空Handler消息队列。
摘要由CSDN通过智能技术生成

}
// 若池内无消息对象可复用,则还是用关键字new创建
return new Message();

}

步骤3:在工作线程中发送消息到消息队列

具体使用

mHandler.sendMessage(msg);

源码分析

/**

  • 源码分析:mHandler.sendMessage(msg)
  • 定义:属于处理器类(Handler)的方法
  • 作用:将消息 发送 到消息队列中(Message ->> MessageQueue)
    */
    public final boolean sendMessage(Message msg)
    {
    return sendMessageDelayed(msg, 0);
    // ->>分析1
    }

/**

  • 分析1:sendMessageDelayed(msg, 0)
    **/
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
    if (delayMillis < 0) {
    delayMillis = 0;
    }

return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
// ->> 分析2
}

/**

  • 分析2:sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)
    **/
    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    // 1. 获取对应的消息队列对象(MessageQueue)
    MessageQueue queue = mQueue;

// 2. 调用了enqueueMessage方法 ->>分析3
return enqueueMessage(queue, msg, uptimeMillis);
}

/**

  • 分析3:enqueueMessage(queue, msg, uptimeMillis)
    **/
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    // 1. 将msg.target赋值为this
    // 即 :把 当前的Handler实例对象作为msg的target属性
    msg.target = this;
    // 请回忆起上面说的Looper的loop()中消息循环时,会从消息队列中取出每个消息msg,然后执行msg.target.dispatchMessage(msg)去处理消息
    // 实际上则是将该消息派发给对应的Handler实例

// 2. 调用消息队列的enqueueMessage()
// 即:Handler发送的消息,最终是保存到消息队列->>分析4
return queue.enqueueMessage(msg, uptimeMillis);
}

/**

  • 分析4:queue.enqueueMessage(msg, uptimeMillis)
  • 定义:属于消息队列类(MessageQueue)的方法
  • 作用:入队,即 将消息 根据时间 放入到消息队列中(Message ->> MessageQueue)
  • 采用单链表实现:提高插入消息、删除消息的效率
    */
    boolean enqueueMessage(Message msg, long when) {

…// 仅贴出关键代码

synchronized (this) {

msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;

// 判断消息队列里有无消息
// a. 若无,则将当前插入的消息 作为队头 & 若此时消息队列处于等待状态,则唤醒
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;

// b. 判断消息队列里有消息,则根据 消息(Message)创建的时间 插入到队列中
for (;😉 {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}

msg.next = p;
prev.next = msg;
}

if (needWake) {
nativeWake(mPtr);
}
}
return true;
}

// 之后,随着Looper对象的无限消息循环
// 不断从消息队列中取出Handler发送的消息 & 分发到对应Handler
// 最终回调Handler.handleMessage()处理消息

总结
Handler发送消息的本质 =
将消息对象的target属性设置为当前Handler实例(将Message绑定到Handler,使执行消息循环时将消息派发给对应的Handler实例)
获取对应的消息队列对象MessageQueue,调用MessageQueue.enqueueMessage(),将Handler需发送消息入队到绑定线程的消息队列中。

之后,随着Looper对象的无限消息循环,不断从消息队列中取出Handler发送的消息&根据target分发到对应Handler,最终回调Handler.handleMessage()处理消息

源码总结

在这里插入图片描述

在这里插入图片描述

工作流程总结

在这里插入图片描述

方式2:使用 Handler.post()
步骤1:在主线程中创建Handler实例

具体使用

private Handler mhandler = new Handler();
// 与方式1的使用不同:此处无复写Handler.handleMessage()

源码分析

/**

  • 源码分析:Handler的构造方法
  • 作用:
  • a. 在此之前,主线程创建时隐式创建Looper对象、MessageQueue对象
    
  • b. 初始
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值