平台
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); 移出了队列.
所以这个问题是, 自己挖坑, 再把自己埋了...