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); 移出了队列.


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


相关文章
|
Android开发
[置顶] 我的Android进阶之旅------&gt;Android解决异常: startRecording() called on an uninitialized AudioRecord.
今天使用AudioRecord进行录音操作时候,报了下面的异常。 E/AndroidRuntime(22775): java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
2602 0
|
3月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
XML 存储 移动开发
Android基础 | 关于Activity你应该明白的一切
Activity 作为一个老生常谈的话题,它是我们刚接触Android开发就遇到,虽然已有一段时间开发经验,但谈起完全搞懂Activity相关,不敢妄言,故结合个人理解及书籍参考,简单总结一下 Activity基础相关知识,其中也留出了一些有意思的问题。
260 0
|
消息中间件 Java 调度
Android 彻底掌握 Handler 看这里就够了(上)
Handler 允许你发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。每个 Handler 实例都与一个线程和该线程的消息队列相关联。当你创建一个新的 Handler 时,它会绑定到一个 Looper。它会将消息和可运行对象传递到该 Looper 的消息队列,并在该 Looper 的线程上执行它们。
417 0
Android 彻底掌握 Handler 看这里就够了(上)
|
消息中间件 Linux Android开发
Android 彻底掌握 Handler 看这里就够了(下)
重点关注 Handler 的 post(Runnable) 与 sendMessage(Message msg) 有什么区别 Handler.post() Handler.getPostMessage() Handler.sendMessage() Handrle.dispatchMessage() Handrle.handleCallback() Looper.loop() 为什么不会阻塞主线程 MessageQueue.next() MessageQueue.nativePollOnce() android_os_MessageQueue_nativePollOnce
237 0
Android 彻底掌握 Handler 看这里就够了(下)
|
Android开发
Android之Handler和Loooper源码分析(2)
Android之Handler和Loooper源码分析
131 0
|
Android开发
Android之Handler和Loooper源码分析(1)
Android之Handler和Loooper源码分析
109 0
|
Android开发
Android之Handler和Loooper源码分析(3)
Android之Handler和Loooper源码分析
138 0
|
XML 开发工具 Android开发
彻底搞清楚Android中的 Attr
版权声明:本文为sydMobile原创文章,转载请务必注明出处! https://blog.csdn.net/sydMobile/article/details/79978187 相信这个词对于Android开发者来说十分熟悉了,那么你对他到底有多了解呢? 回忆起我刚开始接触Android的时候对这三个词有一些迷惑,有些时候只知道一些基本的使用,总之是有迷惑把。
1404 0
|
Android开发 定位技术 存储