当前位置:   article > 正文

Android Handler.postDelayed 挖坑记_android studio mhandler.postdelayed

android studio mhandler.postdelayed

平台

  RK3288 + Android 7.1 + AndroidStudio 4.0.1

问题

    使用Handler

Handler.postDelayed(Runnable, Int)

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

分析

  Handler 部分的代码:

  1. static class H extends Handler{
  2. final static int MSG_REFRESH_TIME = 0;
  3. WeakReference<KidsLauncher> a;
  4. H(KidsLauncher lk){
  5. a = new WeakReference<>(lk);
  6. }
  7. @Override
  8. public void handleMessage(Message msg) {
  9. switch(msg.what){
  10. case MSG_REFRESH_TIME:
  11. a.get().refreshTime();
  12. break;
  13. }
  14. }
  15. /*@Override
  16. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
  17. Logger.d("sendmessageAtTime " + msg.what + " " + uptimeMillis + ":" + SystemClock.uptimeMillis());
  18. return super.sendMessageAtTime(msg, uptimeMillis);
  19. }*/
  20. }
  21. void refreshTime(){
  22. tvTime.setText(TimeUtils.getTimeString());
  23. h.removeMessages(H.MSG_REFRESH_TIME);
  24. h.sendEmptyMessageDelayed(H.MSG_REFRESH_TIME, 1000);
  25. }

尝试过的解决方案:

  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

  1. //frameworks/base/core/java/android/os/Handler.java
  2. public final boolean postDelayed(Runnable r, long delayMillis)
  3. {
  4. return sendMessageDelayed(getPostMessage(r), delayMillis);
  5. }
  6. private static Message getPostMessage(Runnable r) {
  7. Message m = Message.obtain();
  8. m.callback = r;
  9. return m;
  10. }
  11. public final boolean sendMessageDelayed(Message msg, long delayMillis)
  12. {
  13. if (delayMillis < 0) {
  14. delayMillis = 0;
  15. }
  16. return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
  17. }
  18. public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
  19. MessageQueue queue = mQueue;
  20. if (queue == null) {
  21. RuntimeException e = new RuntimeException(
  22. this + " sendMessageAtTime() called with no mQueue");
  23. Log.w("Looper", e.getMessage(), e);
  24. return false;
  25. }
  26. return enqueueMessage(queue, msg, uptimeMillis);
  27. }

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

再看下面这段代码:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. h = new H(this);
  5. h.postDelayed(new Runnable() {
  6. @Override
  7. public void run() {
  8. Logger.d("run in post Delayed");
  9. }
  10. }, 2000);
  11. h.removeMessages(0);
  12. }

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

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

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

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号