handler.postDelayed() 的执行过程

Handler消息机制,postDelayed会造成线程阻塞吗?对内存有什么影响? 每开启一个App,就相当于开启一个新的线程。Handler导致内存泄漏一般发生在发送延迟消息的时候,当Activity关闭之后,延迟消息还没发出,那么主线程中的MessageQueue就会持有这个消息的引用,而这个消息是持有Handler的引用,而handler作为匿名内部类持有了Activity的引用,所以就有了以下的一条引用链。其根本原因是因为这条引用链的头头,也就是主线程,是不会被回收的,所以导致Activity无法被回收,出现内存泄漏,其中Handler只能算是导火索。 阅读详情

今天做项目看到这段代码时产生了一些疑惑,又打开 Handler 源码看了看相关的逻辑。简短的几行代码背后却有着复杂的逻辑。真是越看越爽啊!!!

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
       // do something
    }
},2000);

handler 的 postDelayed()方法的流程:

1.执行 postDelayed 方法

public final boolean postDelayed(Runnable r, long delayMillis)
{
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

2.通过 getPostMessage 方法把 runnable 对象封装成为 message 对象中的 callback 属性

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

3.执行 sendMessageDelayed 方法

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

4.执行 sendMessageAtTime 方法

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

5.最后通过 enqueueMessage 方法把 msg 添加到 enqueueMessage 中,并把发送消息的 handler 对象赋值到 msg.target 属性中

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this; // 把发送消息的 handler对象赋值到 msg.target 属性中
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

6.在 Looper 中循环取出 queue 中的 msg,执行 msg.target.dispatchMessage(msg); 调用 handler 中的 dispatchMessage(msg); 方法分发消息

public static void loop() {
    final Looper me = myLooper(); // 返回当前 looper
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) { // 循环取出queue 中的msg
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }

        // This must be in a local variable, in case a UI event sets the logger
        。。。
        final long end;
        try {
            msg.target.dispatchMessage(msg); // 使用发送消息的 handler 分发消息
            end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        。。。。

        msg.recycleUnchecked();
    }
}

7.执行 handler 的 dispatchMessage 方法,判断 msg 的类型,此时的 msg.callback 不为 null ,执行 handleCallback(msg)

/*
* 根据 msg 的不同类型分发消息
*/
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {// 
        handleCallback(msg);// 这时执行这里,在handler.post(runnable)或 postDelayed(runnable,1000)的时候
    } else {
        if (mCallback != null) { // mCallback :是在创建 handler 的时候,通过构造方法里的参数 Callback 传入的,也就是 new Handler(callback);
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg); // 通过无参的构造函数创建,也就是 new Handler();
    }
}

8.在 handleCallback 中执行 run 方法

private static void handleCallback(Message message) {
    message.callback.run();
}

9.也就是 postDelayed 方法中的 runnable 中的 run , 完成整个消息的发送与处理

/* * The runnable will be run on the thread to which this handler
     * is attached.
*/
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
  // 这里仍然是在ui线程中执行(因为handler 是在ui线程中)
 }
},2000);

这已经是第三次看 Handler 源码了,虽然还是有很多地方不理解,但相比之前已经理解了很多了,对于不理解的东西还是多看,书读百遍,其义自现,还是很有道理的,别忘了在看的时候做好笔记,哪怕现在理解的不是很正确,也要记录下来,下次再看的时候,对照着以前的笔记看,就会发现以前是哪里不理解,该怎么理解才对。今天就先看这些了,下次遇到问题再继续看吧!

new Handler().postDelayed() 延迟intent跳转 //延迟两秒跳转 new Handler().postDelayed(new Runnable() { @Override public void run() { Intent intent=new Intent(MainActivity.this, Leansons.class); startActivity(intent); } }, 20 阅读详情

相关推荐

直线电机驱动技术原理与应用解析

直线电机作为直接电能-直线运动转换装置,其核心原理基于电磁感应定律和洛伦兹力公式。通过三相交流电在定子绕组中产生行波磁场,与动子永磁体相互作用实现精准推力控制。相比传统旋转电机传动系统,直线电机具有零传动间隙、高动态响应(加速度可达10g)和微米级定位精度等技术优势,这使其成为半导体光刻机、精密数控机床等高端装备的关键驱动部件。现代直线电机驱动单元通常采用三环控制架构(电流环、速度环、位置环),配合SiC功率器件和高分辨率光栅反馈,实现纳米级运动控制。随着模块化设计和直接冷却技术的发展,直线电机正朝着更高功

weixin_26802933的博客 259

Handler的postDelayed流程

Handler的post系列方法用来执行一个线程。 比如: mhandler.postDelayed(runnable, 1000); Handler的postDelayed方法其实也是通过sendMessageDelayed方法实现的。 public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); }

longge33445的博客 5073

MATLAB实战:手把手教你用三频四步相移法搞定结构光三维重建(附完整代码)

本文详细介绍了如何使用MATLAB实现三频四步相移法进行高精度结构光三维重建。通过光栅图像预处理、相位计算、多频外差与相位解包裹等步骤,结合完整代码示例,帮助读者掌握从二维图像到三维点云的关键技术。该方法在工业检测和逆向工程中具有抗干扰能力强、高分辨率和鲁棒性等优势。

weixin_29201933的博客 338

Handler的postDelayed方法

前几天我们自己的设备很卡,卡到跳转界面都需要不到1秒的时间,我就把跳转的动作放在Runnable里边,外边加上弹出进度提示框。//要做的事情,这里再次调用此Runnable对象,以实现每两秒实现一次的定时器操作。当然,你也可以做一个闹钟提醒延时的函数试试,比如,先用MediaPlayer播放闹钟声音,如果不想起,被停止播放之后,下次就5分钟后再播放,再被停止的话,下次就4分钟后播放,如果其所在的线程是UI线程的话,Runnable中还是不能执行耗时操作,不然会ANR。实际上也就实现了一个2s的一个定时器。

u014598642的专栏 1670

解决Windows无法卸载补丁的实用方法

无法卸载Windows补丁可能是一个棘手的问题,但通过上述方法,你应该能够找到解决方案。无论是通过控制面板、命令提示符还是手动重置Windows更新组件,都有可能成功卸载问题补丁。如果所有方法都无效,系统还原将是一个值得尝试的备选方案。希望这篇文章能帮助你解决无法卸载补丁的问题。

mmoo_python的博客 1万+

Java后端开发实战:手把手教你用e签宝API搞定电子合同签署(附完整代码)

本文详细解析了Java后端开发中如何通过e签宝API实现电子合同签署的全流程,包括环境配置、核心架构设计、Token管理、签署流程实现及回调处理等关键环节。通过完整的代码示例和最佳实践,帮助开发者高效集成电子签名服务,提升企业数字化转型效率。

weixin_42662293的博客 530

Handler postDelayed的实现原理

Handler postDelayed的实现原理 问题描述 Handler.postDelayed()的原理是如何保证延时执行的? 扩展:这样实现的好处是什么? 题目分析 猜测一下 以我们对Handler的了解,内部使用了Looper对消息队列进行循环获取执行,所以我们估计postDelayed()是Handler内部搞了一个定时器, 定时器到了delayed的时间就把消息加入到消息队列中,让lo...

u012944685的专栏 3589

解决 NLPIR (中科院分词) License 过期问题

因为学习需要,使用到了中文分词技术,网上搜索一番,最终选择了名气比较大的中科院分词器(NLPIR/ICTCLAS)。 用了几个月之后突然报错: E:\code\URLClassifier\Data\NLPIR.user Not valid license or your license expired! Please feel free to contact pipy_zhan

勇敢向前冲 1万+

Android View之View.post()分析

大家都知道每个View都有一个post()和postDelayed()方法,那么这两个方法是做什么用呢?什么时候需要用呢?我们带着这两个问题来分析一下:首先我们看下这两个方法的源码,首先看post():/** * <p>Causes the Runnable to be added to the message queue. * The runnable will be run on ...

weixin_33916256的博客 158

红队内网攻防渗透:内网渗透之内网对抗:实战项目&VPC1打靶&PHP-RCE&三层代理路由&防火墙上线&密码喷射&域控提权

上面已经抓取到了密码,但是我们通过拓扑分析看,要想上线win10只能通过正向shell,因为win7的防火墙是开的,win10反向主动连接肯定入站规则拦截,而win10自己没有开防火墙,所以win7主动正向连接就可以上线。win7开启了防火墙,入站规则肯定是会拦截我们的请求的,所以我们需要反向上线,让win7主动来连接我们。这里扫描发现是存在ms17010漏洞的,但是想上线192.168.2.142的话,我们没有路由是上线不了的,这里有两种办法:一种msf直接生成后门,另一种cs移植后门到msf。

HACKONE的博客 909

一种基于机载LiDAR点云电力线自动提取方法

文章目录一、引言二、算法实现2.1实现步骤2.2实现代码 一、引言 二、算法实现 2.1实现步骤 (1)首先采用首先采用高程滤波方法去除地面点和低矮地物点,滤波后的点云数据中除电力线点云外还含部分杆塔点、高植被点和噪声点。 (2)根据点云空间维度特征提取电力线点,使用空间密度聚类的方法实现单根电力线精确分离。 2.2实现代码 在这里插入代码片 ...

dayuhaitang1的博客 5171

Handler.postDelayed()是如何精确延迟指定时间的

使用Handler.postDelayed()时的疑问 使用handler发送消息时有两种方式,post(Runnable r)和post(Runnable r, long delayMillis)都是将指定Runnable(包装成PostMessage)加入到MessageQueue中,然后Looper不断从MessageQueue中读取Message进行处理。 然而我在使用的时候就一直有一...

zhangcanyan的博客 1万+

PID、模糊PID、SkyHook、LQR、H2/H∞、ADRC等悬架控制合集

PID、模糊PID、SkyHook、LQR、H2/H∞等悬架控制合集

Mr.邹的博客 2013

Handler.postDelayed()的原理

阅读之前先问大家一个问题:Handler.postDelayed()是先delay一定的时间,然后再放入messageQueue中,还是先直接放入MessageQueue中,然后在里面wait delay的时间?为什么?如果你不答不上来的话,那么此文值得你看看。 Handler.postDelayed()的调用路径 Handler.postDelayed(Runnable r, l...

cmyperson的博客 1087

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Handler.postDelayed()无效

在项目使用 Handler.postDelayed() 延时执行任务,却发现无效,代码如下: private Handler mHandler = new Handler(); boolean ret = mHandler.postDelayed(new Runnable() { @Override public void run() { ...

awodefengduanwu的博客 1708

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

你真的懂Handler.postDelayed()的原理吗?

转载自http://www.dss886.com/2016/08/17/01/ 阅读之前先问大家一个问题:Handler.postDelayed()是先delay一定的时间,然后再放入messageQueue中,还是先直接放入MessageQueue中,然后在里面wait delay的时间?为什么?如果你不答不上来的话,那么此文值得你看看。 原文: 使用han

qingtiantianqing的博客 5万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

android handler postdelayed 传参数,Android Handler postDelayed的原理

前言我们经常用Handler中的postDelayed方法进行延迟操作,像这样new Handler().postDelayed(new Runnable() {@Overridepublic void run() {//操作内容}},100);我们都知道Handler的机制是将消息通过sendMessage()放入到MessageQueen中 然后looper轮训器通过轮训取出MessageQu...

weixin_39639040的博客 1098

Handler sendMessageDelayed()/postDelayed()机制详解

Thread/Hander/Looper是Android在Java线程基础之上提供的线程通信/消息处理机制,这个众所周知,不再细说。Handler提供了两个发送延迟处理任务的api: /** * Enqueue a message into the message queue after all pending messages * before (current time + delayM

@甘道夫@的专栏 2万+

面试:Handler.postDelayed()精确延迟指定时间的原理

使用handler发送消息时有两种方式,post(Runnable r)和post(Runnable r, long delayMillis)都是将指定Runnable(包装成PostMessage)加入到MessageQueue中,然后Looper不断从MessageQueue中读取Message进行处理。 然而我在使用的时候就一直有一个疑问,类似Looper这种「轮询」的工作方式,如果在每次读取时判断时间,是无论如何都会有误差的。但是在测试中发现Delay的误差并没有大于我使用System.out.p

王温暖的博客 3280

Android Handler postDelayed的原理

前言 我们经常用Handler中的postDelayed方法进行延迟操作,像这样 new Handler().postDelayed(new Runnable() { @Override public void run() { //操作内容 } },100); 我们都知...

dodod2012的专栏 1769

Handler的postDelayed原理

背景 问题一 Handler.postDelayed()是先delay一定的时间,然后再放入messageQueue中,还是先直接放入MessageQueue中,然后在里面wait delay的时间?为什么? 问题二 如果Message会阻塞MessageQueue的话,那么先postDelay10秒一个Runnable A,消息队列会一直阻塞,然后我再post一个Runnable B,B岂不是会...

ruanyandong的博客 886

java postdelayed_如何取消postDelayed()的执行

我正在制作一个应用程序,其中某些小部件即时创建,可以通过拖放进行重新排列。我试图实现两件事情:如何取消postDelayed()的执行长按启动拖放短按(或点击)打开菜单更改某些设置。但我有一个问题,我无法取消处理程序的postdelayed()函数中的代码。我正在使用下面的代码来实现它。_sliders_item[_sliders_counter].setOnTouchListener(new V...

weixin_42171208的博客 1847

Handler.postDelayed()工作原理

转载:https://blog.csdn.net/qingtiantianqing/article/details/72783952 原文: 使用handler发送消息时有两种方式,post(Runnable r)和post(Runnable r, long delayMillis)都是将指定Runnable(包装成PostMessage)加入到MessageQueue中,然后Looper不断...

滴水穿石,不断积累! 1020

java postdelayed_你真的懂Handler.postDelayed()的原理吗?

转载自http://www.dss886.com/2016/08/17/01/阅读之前先问大家一个问题:Handler.postDelayed()是先delay一定的时间,然后再放入messageQueue中,还是先直接放入MessageQueue中,然后在里面wait delay的时间?为什么?如果你不答不上来的话,那么此文值得你看看。原文:使用handler发送消息时有两种方式,post(Ru...

weixin_32373123的博客 885
上一篇: 用 ffmpeg 实现批量剪切视频
下一篇: Tablayout 和 ViewPager 联用时,向 Fragment 传值的问题
windylimiao
博客等级 码龄10年 48粉丝 44原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值