平台

  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 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);    }

尝试过的解决方案:

  1. 使用new Handler().postDelayed                      => 问题依旧
  2. 使用new Handler().postDelayed, delayed = 0 => 问题解决, 但无法延时
  3. 使用Handler.post()                                           => 问题解决, 但无法延时
  4. 使用Handler.sendEmptyMessageDelayed      => 问题解决
  5. 使用Handler.sendMessageDelayed                => 问题解决
  6. 使用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); 移出了队列.

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

 

 

更多相关文章

  1. Android 功能代码总结
  2. android 分享到 代码
  3. Android中NFC功能流程图解析及代码演示『轉』
  4. android 关于 发送post请求的代码总结(包含加上参数)
  5. Android Audio代码分析12 - stream type续
  6. android代码常识

随机推荐

  1. Android腾讯微薄客户端开发教程汇总
  2. Android(安卓)相对布局 RelativeLayout
  3. Android音频简介
  4. ImageView---属性android:background与andro
  5. vue.js的h5页面与android(WebViewJavascr
  6. Android(安卓)RelativeLayout常用属性~
  7. android(2)——Structure of an Android(
  8. Android界面设计之:使用水平视图切换
  9. ffmpeg htc
  10. 【Android布局】在程序中设置android:gra