mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法

mars的Android视频开发教程第14讲中的后半部分以一个例子讲解了应用Handler控制进度条的方法。先贴上代码:
mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第1张图片 
mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第2张图片

mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第3张图片

主要看最后几行带代码,我这里只是把if语句和updateBarHandler.sendMessage(msg);语句换了下位置,并且将条件“1==100”改为了“i>100”,但其在LogCat中的输出结果是一样的。为了方便观察结果,我把打印输出值改为了i,并在if语句中打印输出“结束” ,在LogCat中的输入如下所示: mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第4张图片

由上图可以看出,当i>100时,线程并没有因为执行了updateBarHandler.removeCallbacks(updateThread);语句而消亡,这是为什么呢?
这就要分析代码的执行机理了,刚开始我按照按照视频上把if语句放在了updateBarHandler.sendMessage(msg)之后,发现点击按钮之后,线程一直在运行,并没有因为i>100而终止。我觉得应该是因为updateBarHandler.sendMessage(msg)语句先把Message对象加入到消息队列当中,而后转到了updateBarHandler类中,执行public void handleMessage(Message msg)方法,在这个方法中有updateBarHandler.post(updateThread)语句,因此当i>100时,在执行updateBarHandler.removeCallbacks(updateThread)从队对立中移除线程之前,再次把线程加入了队列中,所以线程会一直执行,不会消亡。
如果按照这个逻辑的话,把updateBarHandler.sendMessage(msg)放在if语句之后应该就可以在执行updateBarHandler.sendMessage(msg)之前把线程从队列中移除掉了,这样就不会把Message对象加入到消息队列当中,从而不会调用public void handleMessage(Message msg)方法,也就不会执行该方法中的updateBarHandler.post(updateThread)语句,那么便可以结束线程了,但最终在LogCat中的输出与没有调换二者的位置之前是一样的。
后来加上了else语句,如下所示:
  mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第5张图片

这次得到的输出结果如下所示:
mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第6张图片
很明显可以看出,线程在i>100之后终止了,从输出结果的比较看,加else的应该没有执行updateBarHandler.sendMessage(msg)语句,而不加else时,应该是执行了updateBarHandler.sendMessage(msg)语句,从而再次将线程加入到了队列中。
首先明确一点,这里只有一个主线程,由于没有条用start()方法,因此Runnalbe接口生成的线程没有独立开辟出来,而是在主线程中执行,再次,这儿有两个队列,一个是消息队列,另外一个是线程队列。在网上search了下,还是蛮多人遇到这个问题的,但是对问题的分析不一,有一些分析很明显的是错误的,具体原因目前我也不太确定。但我一直在思考一个问题,可以在本线程正在执行的时候在该线程内部将本线程从线程队列中移除吗?如果不行,那就能说通了。updateBarHandler.removeCallbacks(updateThread)语句不能将线程移除,那么在线程结束前便会执行updateBarHandler.sendMessage(msg)语句(这样看来,if语句中的updateBarHandler.removeCallbacks(updateThread)语句似乎不起什么作用,事实确实如此,我把该语句注释掉,依然能输入上图的结果),又再次将线程加入到了线程队列,这样便陷入了死循环, 如果加上else语句,便不会执updateBarHandler.sendMessage(msg)语句,这样便终止了该线程。
另外,也可以采用如下方法解决:
  mars Android视频第14讲中代码出现的错误分析——Handler中的removeCallbacks方法_第7张图片

这里只需在i>100时返回即可,下面的updateBarHandler.sendMessage(msg)语句也便不会执行。
当然还有很多种方法在理论上应该是可以行得通的,比如在线程中将消息对象从消息队列中移除,或者在执行消息时将线程从线程队列中移除,大家不妨测试下。
 
 

关注我的新浪博客:http://blog.sina.com.cn/u/1921993171

关注我的新浪微博:http://weibo.com/u/1921993171?wvr=5&wvr=5&lf=reg

你可能感兴趣的:(Android之旅,线程,handler,Android,队列)