今天在项目中遇到这样一个问题 :
同一个页面要求多次显示气泡消息Toast,即重复显示,重复显示的问题网上有解决方案,下面还会有介绍,我这里已经解决这个,真正碰到的问题来了,我用了不同的设备(设备主要区别是系统版本不同,一个android2.2,一个2.3.6,一个4.1.1)对程序功能进行测试,结果发现有的能正常显示,有的却只显示第一个Toast,后面的不再显示。
好了 问题描述完成,下面是解决过程:
1.Toast重复显示问题(为什么要说明这个呢?继续看你就知道了)
Toast重复显示不能直接重复编写,需要处理一下以避免造成用户使用的不便,详细解决方案请参考:http://mwxboy.diandian.com/post/2012-04-25/19583598,关键代码粘贴一下:
private static void showMessage(Context context,String aMsg, int gravity, int xOffset, int yOffset)
{
//第一调用showMessage()进的是else,同一页面第二次调用进的是if,因为context相同
if(mContext == context)
{
mToast.cancel();//这句是造成后面问题的关键
mToast.setText(aMsg);
}
else
{
mContext = context;
mToast = Toast.makeText(mContext, null, 0);
mToast.setGravity(gravity, xOffset, yOffset);
mToast.setText(aMsg);
}
mToast.show();
}
2.用上面的代码是解决了android中Toast的重复显示问题,但是注意,这个方法在Android 4.0版本以下的系统中不会引起我碰到的那个问题(这是我后面才发现的)。看完上面的代码,我打算研究了一下Toast的cancel()方法(因为考虑引起后面问题的是不是Toast占用和释放的原因,而Toast中的cancel()就是这样一个类似功能的方法),从网上一篇相关文章中得到启示,地址:http://dkmeteor.iteye.com/blog/1399646,
最主要的启示是该文章的最后几句:
2月28日追加:
实测 在2.2 2.3中此方法工作良好。
在4.0系统中效果极差
多次触发Toast 无法正常显示
从这几句话我确定了是cancel()在4.0系统中的使用有问题,于是我试着把 mToast.cancel();这句代码注释掉,调试通过,问题居然就解决了 ,在2.2和2.3中也没有问题了 。
由于花了点时间解决这个bug,所以记录下来给自己也给大家分享一点经验,可能不是完全正确,欢迎大家拍砖!
2013.01.18追加:
今天网上搜索android4.0 Toast.cancel()发现这篇文章,地址:http://blog.csdn.net/sylcc_/article/details/7396452,里面介绍了4.0中cancel源码和其他版本的不同,从这里得到昨天碰到问题的根本原因,在此感谢该文章的原创作者。下面贴出里面的一个片段:
”下面是2.2和4.0中Toast源码的链接:
http://www.oschina.net/code/explore/android-2.2-froyo/android/widget/Toast.java
http://www.oschina.net/code/explore/android-4.0.1/core/java/android/widget/Toast.java
比较两者关于cancel()处理的差异发现了如下差异:
在4.0中如下:
final Runnable mHide = new Runnable() {
public void run() {
handleHide();
// Don't do this in handleHide()because it is also invoked by handleShow()
mNextView = null;
}
};
而2.2中没有mNextView = null;这一行代码。
再查看show()中有如下源码:
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
所以判断产生的Bug的原因是2.2系统和4.0系统对cancel的处理的差异造成的,将cancel注释就可以正常显示了。“
但是4.0以下系统需要用到cancel()怎么办?下面是另一篇文章 http://blog.csdn.net/gouguofei/article/details/7814195 给出的一个解决办法,贴出片段:
“但是注释掉以后对4.0以下的系统需要cancel()怎么办呢,这里我的解决办法是在程序里获取系统版本,如果是4.0及以上就不执行cancel(),否则执行cancel()。 ”
获取系统版本比较简单:int version = Integer.valueOf(android.os.Build.VERSION.SDK) 即可获得