记一次handler removeCallback问题

N久没有更新博客了,先发一篇备忘录里缓存的问题解决记录吧,24年要重新开始努力~


首先回忆一波知识点
Handler -> Looper -> MessageQueue

hander持有looper,looper和线程绑定,并且持有一个消息队列MQ

那么,每次 new Handler的时候提供一个相同的Looper,是否可以remove前一个添加到MQ的Message


demo

// 回掉线程
var cacheRunnable: Runnable? = null

/**
 * 1秒内顶多执行一次线程
 */
fun function(item: BEAN?) {
    // 移除线程
    if (cacheRunnable != null) {
        cacheRunnable?.let { Handler(Looper.getMainLooper()).removeCallbacks(it) }
    }
    // 初始化线程
    cacheRunnable = Runnable {
        handleData(item)
    }
    // 一秒后执行线程
    cacheRunnable?.let { Handler(Looper.getMainLooper()).postDelayed(it, 1000L) }
}

答案是不可以的

Handler:

/**
 * Remove any pending posts of Runnable r that are in the message queue.
 */
public final void removeCallbacks(@NonNull Runnable r) {
    mQueue.removeMessages(this, r, null);
}

MessageQueue:

void removeMessages(Handler h, Runnable r, Object object) {
    if (h == null || r == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h && p.callback == r
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.callback == r
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

可以看到,MQ是通过单项列表管理的Message,removeMessage的时候,会同时比对target(Handler)和 callback(Runnable),所以每次去new Handler的方案是无效的。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值