Android(安卓)Handler removeMessages引发postDelayed失效的问题
16lz
2021-01-24
最近遇到一个使用Handler removeMessages时使 使用boolean postDelayed(Runnable r, long delayMillis)函数post的Runnable也被删除而没有执行的问题,具体如下:
public class MainActivity extends Activity {static final String TAG_STRING = "Main";enum MSG_ID {ID_FIRST,ID_SECOND,ID_THRED}Handler mHandler = new Handler() {@Override public void handleMessage(Message msg) {Log.e(TAG_STRING, " handleMessage what = " + msg.what); }}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e(TAG_STRING, "onCreate"); mHandler.sendEmptyMessageDelayed(MSG_ID.ID_FIRST.ordinal(), 1000); mHandler.postDelayed(new Runnable() {@Overridepublic void run() {Log.e(TAG_STRING, "run");}}, 1000); mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal()); } }
当 mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());这行被屏蔽时,打印如下: 01-03 04:08:36.362: E/Main(663): onCreate 01-03 04:08:37.372: E/Main(663): handleMessage what = 0 01-03 04:08:37.372: E/Main(663): run 当 mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());这行被打开时,打印如下 01-03 04:12:28.372: E/Main(709): onCreate
我们看到 mHandler.postDelayed的Runnable也没有执行了。
查看一下postDelayed的源码,如下:
public final boolean postDelayed(Runnable r, long delayMillis){ return sendMessageDelayed(getPostMessage(r), delayMillis);}
getPostMessage的源码如下:
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
Message.obtain()的代码如下:
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); }
以上代码最终会执行到 return new Message();
Message的构造函数为空 public Message() { }
那么Message的what成员被默认赋值为0. 所以当删除消息ID值为0的消息时,如:
mHandler.removeMessages(MSG_ID.ID_FIRST.ordinal());
使用postDelayed post出去的Runnable, 如果还没被执行, 也会被删除掉。与此相同的还有 public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); }
为了避免以上问题的发生, 用户应该避免使用消息ID值为0的消息, 如:
enum MSG_ID {ID_NOT_USE,ID_FIRST,ID_SECOND,ID_THRED}
更多相关文章
- C语言函数的递归(上)
- Logger详解(二)
- 实例教程五:采用SharedPreferences保存用户偏好设置参数
- Android中结合OrmLite for android组件对SQLite的CRUD(增删改查)
- PackageManagerService(Android5.1)深入分析(四)安装应用
- Android跨进程通信IPC之16——Binder之native层C++篇--获取服务
- 从Process xxxx (pid xxx) has died分析
- Android(安卓)开发中的 Handler ,Thread ,Message ,Runnable 的
- Android之Handler详解(四)