关于Android中调用了post方法后貌似没有执行run方法的解释及解决办法

来源:互联网 发布:显示器架子 淘宝 编辑:程序博客网 时间:2024/05/18 09:11

(真纠结,刚刚发了之后才发现排版太乱了,稍作修改再发了哈~)


哎……之前纠结过Handler的运行机制,后来貌似懂了,但是近几天又被自己的工程绕的好像又不懂了一样!!


其实之前理解还是对的哈~只是这次的工程里的各个变量和对象的定义和初始化位置不适当才造成表面上貌似handler没有像SDK上所说的那样运行似的…………


首先,先讲几点注意点:

1、  创建一个线程并启动该线程,然后创建一个绑定该线程Looper对象的Handler对象(用HandlerThread类来创建线程的时候会默认为该线程创建相应的Looper对象和消息队列,否则请参考Looper.prepare()等等自行创建哇);

2、  一个线程只对应一个消息队列(不是网上有些地方所说的一个线程队列和一个消息队列!),但是可以对应多个handler对象;

3、  调用post方法也是向MessageQueue发送消息,只不过是将post的的runnable对象包装成Message类型发送(这个不清楚的也可以参考Android的源码中各个API的具体实现)下面稍作介绍:

[java] view plaincopyprint?
  1. public final boolean post(Runnable r)  
  2. {  
  3.    return  sendMessageDelayed(getPostMessage(r), 0);  
  4. }  
以上是Android源码中post方法的实现,可以看到其实调用的也是sendMessageDelayed方法,而我们使用的sendMessage方法也是调用的这个方法实现的(第二个参数为0);

4、  看了上面讲的第三点,可能细心的大家会说,既然也是按照消息发送到MessageQueue中的,那是不是也是在handleMessage中处理呢?其实不是的哈~这个又牵涉到Android源码了(之前一直觉得SDK好强大,but now,我觉得还是源码好哈O(∩_∩)O哈哈~),不管是发送我们所说的真正的消息,还是post我们的runnable对象,源码中最后都会调用dispatchMessage方法把这些消息派发出去,这里要注意的是,如果该方法中正在派发的消息的callback不为空的话,就说明这个其实是个runnable对象,这时候就会调用handleCallback回调方法来处理这个runnable,而这个回调其实就是我们覆写的runnable借口中的run()方法啦~

5、  总结一下上面的两点哈~其实系统在处理我们发送的消息时(不管是post的还是sendMessage的)会有两个分支:一个就是正常的我们所想的handleMessage,还有一个就是调用回调去执行run方法,所以大家看到post调用后却没有进入handleMessage方法中不要奇怪哈~


OK先说上面这几点,虽然没什么难的,但是我真的纠结了好久哇~\(≧▽≦)/~


下面来说题中提到的情况,我们在工程开始的时候调用post方法将runnable对象发送到队列中,正常情况应该会去执行我们覆写的run方法的,但是我的工程就没有哇…………这边代码就不贴出来了,应该是有问题的,所以才没有按照我上面所说的正常情况来跑!


这边就说一下为什么会出现这样的情况,以免出现跟我一样状况的朋友也花那么多时间纠结在这个问题上^_^

其实这边并不是handler运行机制的问题,而是我们初始化对象和这个对象的作用域引起的问题啦~我们如果不在最开始定义runnable对象的时候就初始化,那就会导致在我们dispatchMessage的时候实际上看到的runnable是null,那就相当于告诉系统说“咳咳……我这个是平常寻常以及正常的消息啊,不是post来的runnable对象,所以你不要去调我run的回调啊!不然我跟你没完,哼哼……”,这样系统也就不会去执行你辛辛苦苦给他准备好的run方法了哇~


以上,所以我们最好在定义runnable对象的时候就一起初始化了,不然会发生什么事可就不清楚啦~~~

对了,最后再提醒大家一点哈,一般情况下不要在run方法中用sleep方法来延迟下一次消息的发送,用postDelayed()方法比较保险(相对于后面要removeCallbacks方法而言的哈~~)


纠结了这么久的成果,跟大家一起分享啦~还有,大家如果还是不清楚的话,可以继续看一下我的上一篇Blog,会很有帮助的哟~

原创粉丝点击