Android Handler.postDelayed 挖坑记

简介: Android Handler.postDelayed 挖坑记

平台


 RK3288 + Android 7.1 + AndroidStudio 4.0.1


问题


   使用Handler


Handler.postDelayed(Runnable, Int)

   时, Runnable.run中的代码不执行


分析


 Handler 部分的代码:


static class H extends Handler{
        final static int MSG_REFRESH_TIME = 0;
        WeakReference<KidsLauncher> a;
        H(KidsLauncher lk){
            a = new WeakReference<>(lk);
        }
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
                case MSG_REFRESH_TIME:
                    a.get().refreshTime();
                    break;
            }
        }
        /*@Override
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            Logger.d("sendmessageAtTime " + msg.what + " " + uptimeMillis + ":" + SystemClock.uptimeMillis());
            return super.sendMessageAtTime(msg, uptimeMillis);
        }*/
    }
    void refreshTime(){
        tvTime.setText(TimeUtils.getTimeString());
        h.removeMessages(H.MSG_REFRESH_TIME);
        h.sendEmptyMessageDelayed(H.MSG_REFRESH_TIME, 1000);
    }

尝试过的解决方案:


使用new Handler().postDelayed                      => 问题依旧

使用new Handler().postDelayed, delayed = 0 => 问题解决, 但无法延时

使用Handler.post()                                           => 问题解决, 但无法延时

使用Handler.sendEmptyMessageDelayed      => 问题解决

使用Handler.sendMessageDelayed                => 问题解决

使用View.postDelayed                                     => 问题依旧

查阅相关源码及文章:


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


尝试把上面注释代码放开, 输出LOG, 终于发现了问题所在.


解决


原因: 在应用中, 定义一个消息类型为 MSG_REFRESH_TIME=0; 在启动后, 会自循环更新当前的时间.


考虑下这样一个问题: Handler.post后, 最终enqueueMessage时, Message.what是多少?  答案是 0


//frameworks/base/core/java/android/os/Handler.java
    public final boolean postDelayed(Runnable r, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }
    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    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);
    }


不管是new Message(), 还是Message.obtain(), 在初始时, 基本都是0


再看下面这段代码:


@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        h = new H(this);
        h.postDelayed(new Runnable() {
            @Override
            public void run() {
                Logger.d("run in post Delayed");
            }
        }, 2000);
        h.removeMessages(0);
    }

代码中 "run in post Delayed" 这个LOG, 是不会打印出来的, 原因是, Message已经从队列移除了.


同理, 在使用MSG_REFRESH_TIME 更新时间的时, 执行refreshTime后, 队列中, 所有的带Runnable的Message已经被h.removeMessages(H.MSG_REFRESH_TIME); 移出了队列.


所以这个问题是, 自己挖坑, 再把自己埋了...


相关文章
Autojs4.1.0实战教程---抖音极速版自动评论
Autojs4.1.0实战教程---抖音极速版自动评论
541 1
|
5月前
|
人工智能 运维 自然语言处理
技术思辨|AI Coding:经验壁垒正在失效,工具进化重塑编程
本文探讨AI Coding对传统研发模式的影响,总结5大变化趋势。AI虽降低技术门槛,但专业性并未消失,而是向更高维度转移,如问题定义与批判性思维。高效专注、可复用性及架构设计仍为核心,全栈开发与领域专家角色并存。测试与研发左移减少信息损耗,提升效率。那10%的核心技能包括长程规划、决策制定、创造性解决问题、协作沟通及持续学习能力,是AI时代开发者的关键竞争力。最后强调“老师傅”的经验依然重要,需转变价值体现方式以适应新时代需求。
技术思辨|AI Coding:经验壁垒正在失效,工具进化重塑编程
|
5月前
|
数据可视化 Java 开发工具
在分支回滚后,如何恢复被回滚的代码?
在分支回滚后,如何恢复被回滚的代码?
839 8
|
12月前
|
网络协议 安全 网络安全
OSPF在IPv6环境下的实现
OSPF在IPv6环境下的实现
362 5
|
Java 开发工具 Android开发
OpenCV(一):Android studio jni配置OpenCV(亲测有效,保姆级)
OpenCV(一):Android studio jni配置OpenCV(亲测有效,保姆级)
2104 0
|
Web App开发 设计模式 JavaScript
自动化测试之美:如何利用Selenium实现Web应用的高效测试
【10月更文挑战第29天】在软件开发的世界中,测试是确保产品质量的关键步骤。本文将带你了解如何使用Selenium这一强大的自动化测试工具,提高Web应用测试的效率和准确性。通过实际案例,我们将探索Selenium的核心功能及其在现代软件开发中的应用,旨在帮助读者掌握自动化测试的精髓,从而提升软件测试工作的整体效能。
195 0
|
安全 物联网 网络安全
物联网卡在新疆不能使用的原因
物联网卡不能在新疆使用的原因可能涉及多个方面,这通常与国家政策、网络安全、地区特殊性以及运营商的管理策略有关。以下是一些可能的解释:
|
存储 C++ 内存技术
Keil5使用心得以及知识总结
Keil5使用心得以及知识总结
460 0
|
监控 UED
深入理解Call-ID头字段的重要性
【8月更文挑战第24天】
704 0
|
存储 Java 编译器
JNI内存方面说明以及相关类型手动释放内存
JNI内存方面说明以及相关类型手动释放内存
1430 0