Toast——多次点击只显示一次解决方案

来源:互联网 发布:js取得select选中的值 编辑:程序博客网 时间:2024/05/21 23:00
 


        Android中的Toast是非常好用的一个信息提示控件,但是系统自带的Toast多次点击之后,会出现多次,如显示时间是2S,点击5次之后就会显示5X2=10S。

        针对以上问题,Android为我们提供了一个静态方法cancel(),但是此方法Android4.0版本有所区别,参考:http://www.eyeandroid.com/forum.php?mod=viewthread&tid=1894&page=1

原文如下:

在修复RUI桌面在4.0系统下的提示信息不完善的Bug过程的一些思路与大家分享一下。

Bug描述:

RUI在2.2的系统点击推荐图标下载后,就会进入下载队列中下载,如果再次点击相同的图标就会使用Toast提示“**已经在下载队列中”。但是在4.0的系统就会出现异常,第二次点击相同的推荐图标时没有出现Toast提示。

相关源码:

 

  1. publicstaticvoid showMessage(final Context act,finalint gravity,final String msg) { 
  2.         Toast.makeText(act, msg, Toast.LENGTH_SHORT).show(); 
  3.         new Thread(new Runnable() { 
  4.             public void run() { 
  5.                 handler.post(new Runnable() { 
  6.                     @Override 
  7.                     public void run() { 
  8.                         Log.v(TAG,"showMessage Runnable ThreadID: " + Thread.currentThread()); 
  9.                         synchronized (synLock) { 
  10.                             Log.v(TAG,"showMessage toast text: " + msg); 
  11.                             if (toast != null) { 
  12.                                 Log.v(TAG,"tosat != null"); 
  13.                                // 修复4.0中推荐下载信息不完善 
  14. //                              toast.cancel(); 
  15.                                 toast.setText(msg); 
  16.                                 toast.setDuration(Toast.LENGTH_SHORT); 
  17.                             }else
  18.                                 toast = Toast.makeText(act, msg, Toast.LENGTH_SHORT); 
  19.                             } 
  20. //                          toast.setGravity(gravity, 0, 0); 
  21.                             try
  22.                                 toast.show(); 
  23.                             }catch(Exception e) { 
  24.                                 Log.d(TAG,"Exception " + e.getMessage()); 
  25.                             } 
  26.                             Log.v(TAG,"toast: " + toast); 
  27.                         } 
  28.                     } 
  29.                 }); 
  30.             } 
  31.         }).start(); 
  32.     } 


分析Bug可能产生的原因:

1.      怀疑是context出现问题的原因。

因为Toast.makeText(Contextcontext, CharSequencetext, int duration)中有如下解释:

context The context to use. Usually yourandroid.app.Applicationorandroid.app.Activityobject.

而源码中传入的context是从NetworkService中传入的,所以怀疑这可能是出现Bug的原因。

我将context从Launcher中传入,Toast依然没有出现;直接Toast.makeText(act, msg, Toast.LENGTH_SHORT).show();结果出现Toast提示信息,所以不是context的原因。

2.      怀疑是互斥锁和handler.post()中的原因。

在代码中加入Log信息,从Log打印出来的信息可以得出已经运行到了互斥域内的代码。Log打印出来的运行线程是在主线程中,而且在run的代码中加入Toast.makeText(act, msg, Toast.LENGTH_SHORT),有Toast显示。所以排除了互斥锁和Handler.post()的原因。

经过上述分析后觉得很奇怪,就向其它人请教,让我慢慢调试。

后来看到cancel()的解释如下:

Closethe view if it's showing, or don't show it if it isn't showing yet. You do notnormally have to call this. Normally view will disappear on its own after theappropriate duration.

就怀疑问题出在这里。将代码toast.cancel()注释掉后运行,发现Toast提示信息出现,跟他人汇报后,提示“可以看看4.0中Toast的源码”。

下面是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注释就可以正常显示了。

解决方案一(只适合2.3版本以下):


import android.content.Context;import android.os.Handler;import android.os.Looper;import android.widget.Toast;public class ToastUtil {private static Handler handler = new Handler(Looper.getMainLooper());private static Toast toast = null;private static Object synObj = new Object();public static void showMessage(final Context act, final String msg) {showMessage(act, msg, Toast.LENGTH_SHORT);}public static void showMessage(final Context act, final int msg) {showMessage(act, msg, Toast.LENGTH_SHORT);}public static void showMessage(final Context act, final String msg,final int len) {new Thread(new Runnable() {public void run() {handler.post(new Runnable() {@Overridepublic void run() {synchronized (synObj) {if (toast != null) {toast.cancel();toast.setText(msg);toast.setDuration(len);} else {toast = Toast.makeText(act, msg, len);}toast.show();}}});}}).start();}public static void showMessage(final Context act, final int msg,final int len) {new Thread(new Runnable() {public void run() {handler.post(new Runnable() {@Overridepublic void run() {synchronized (synObj) {if (toast != null) {toast.cancel();toast.setText(msg);toast.setDuration(len);} else {toast = Toast.makeText(act, msg, len);}toast.show();}}});}}).start();}}


 

解决方案二(摒弃系统Toast):

import android.content.Context;import android.graphics.PixelFormat;import android.os.Handler;import android.os.Message;import android.view.Gravity;import android.view.WindowManager;import android.widget.TextView;import android.widget.Toast;public class ToastUtil2 {public static TextView tv;public static WindowManager mWindowManager = null;public static void showMessage(final Context act, final String msg) {mWindowManager = (WindowManager)act.getSystemService(Context.WINDOW_SERVICE);showMessage(act, msg, Toast.LENGTH_SHORT);}public static void showMessage(final Context act, final int msg) {showMessage(act, act.getString(msg), Toast.LENGTH_SHORT);}public static void showMessage(Context context, String msg, int Length){if (tv == null){tv = new TextView(context);tv.setText(msg);tv.setTextSize(20);//tv.setBackgroundResource(R.drawable.bg_layoutinput_focused);tv.setPadding(0, 0, 0, 30);}else{tv.setText(msg);tv.setTextSize(20);//tv.setBackgroundResource(R.drawable.bg_layoutinput_focused);tv.setPadding(0, 0, 0, 30);}if (tv.getParent() == null){WindowManager.LayoutParams params = new WindowManager.LayoutParams();params.gravity = Gravity.BOTTOM;params.alpha = 0.65f;params.x = 0;params.height = WindowManager.LayoutParams.WRAP_CONTENT;params.width = WindowManager.LayoutParams.WRAP_CONTENT;params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;params.format = PixelFormat.TRANSLUCENT;params.windowAnimations = 0;mWindowManager.addView(tv, params);handler.sendEmptyMessageDelayed(101, 1000);}else{tv.setText(msg);handler.removeMessages(101);handler.sendEmptyMessageDelayed(101, 1000);}}static Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (tv.getParent() != null)mWindowManager.removeView(tv);}};public static void cancelCurrentToast(){if (tv != null && tv.getParent() != null){mWindowManager.removeView(tv);}}}


 解决方案三(推荐):

public class ToastUtil3 {private static String oldMsg;protected static Toast toast   = null;private static long oneTime=0;private static long twoTime=0;public static void showToast(Context context, String s){if(toast==null){ toast =Toast.makeText(context, s, Toast.LENGTH_SHORT);toast.show();oneTime=System.currentTimeMillis();}else{twoTime=System.currentTimeMillis();if(s.equals(oldMsg)){if(twoTime-oneTime>Toast.LENGTH_SHORT){toast.show();}}else{oldMsg = s;toast.setText(s);toast.show();}}oneTime=twoTime;}public static void showToast(Context context, int resId){showToast(context, context.getString(resId));}}


 


 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电工超作证丢了怎么办 设计师直接找电梯厂家怎么办 研究生补助申请期限过了怎么办 我的电脑图标没了怎么办 苹果锁频密码忘了怎么办 孕妇被降职降薪怎么办 公司降职降薪员工不同意怎么办 企业因为经营不善要降薪该怎么办 调岗不降薪我该怎么办? 怀孕后强制调岗怎么办 有限公司法人变更后债务怎么办 有限公司法人跑路债务怎么办 网上买票身份信息待核验怎么办 微信买票身份核验失败怎么办 买高铁票待核验怎么办 网上购票身份待核验怎么办 b站稿件版权原因怎么办 已离职老板打电话说账有问题怎么办 开到应急刹车道怎么办 自动挡的车刹车失灵怎么办 自动挡的车如果刹车失灵怎么办 手动挡汽车刹车失灵怎么办 车辆没有年检出了交通事故怎么办 跟着大货车闯了红灯怎么办 在万家金服买的电子产品坏了怎么办 汽车被油笔画了怎么办? 挂到别人车跑了怎么办 浪琴手表保修卡掉了怎么办 事故车辆维修和报废怎么办 4.2货车拉缸了怎么办 工作中与同事发生矛盾怎么办 和领导关系闹僵怎么办 内倒窗户卡住了怎么办 支付宝存在安全风险怎么办 地铁车站空调坏了怎么办 面试防汛值班发生灾情你怎么办 怀孕上班路途太远怎么办 硕士错过校招应该怎么办 收银员收多了钱怎么办 商铺贷款批不了怎么办 铁路局的门面乱收房租怎么办