Android Toast cancel和show 不踩中不会知道的坑

说到Android Toast,几乎都很熟悉吧,下面讲讲怎么实现下面几种场景:

1、连续点击一个按钮,每次都产生一个新的Toast并且调用show方法

问题:触发了toast以后,toast内容会一直排着队的显示出来,不能很快的消失

2、连续点击一个按钮,缓存一个Toast,每次都调用show方法

  推荐:这种方式体验感觉最好,Toast消失的计时会从最后一次show之后才开始计算,还可以通过setText设置不同的内容

3、连续点击一个按钮,缓存一个Toast,每次先调用cancel再调用show方法 

问题:这里有坑,可能cancel之后就show不出来了

4、别人封装的一个列子,介绍了Toast其他的一些问题

下面看下上面1-3种方式的代码写法:

1、连续点击一个按钮,每次都产生一个新的Toast并且调用show方法,这个没什么好说的,都会写

Toast.makeText(context, "要显示的提示", Toast.LENGTH_LONG).show();

2、连续点击一个按钮,缓存一个Toast,每次都调用show方法(推荐写法,体验比较好)

 private Toast mShowingToast;
 private void showTestToast() {
     // mActivity是一个Activity对象,弹Toast一般用Activity类型的Context
     if (mShowingToast == null) {
         mShowingToast = Toast.makeText(mActivity, "要显示的提示", Toast.LENGTH_LONG);
     }
     mShowingToast.show();
 }

3、连续点击一个按钮,缓存一个Toast,每次先调用cancel再调用show方法 (容易踩坑的地方)

private Toast mShowingToast;
private void showTestToast() {
    // mActivity是一个Activity对象,弹Toast一般用Activity类型的Context
    if (mShowingToast == null) {
        mShowingToast = Toast.makeText(mActivity, "要显示的提示", Toast.LENGTH_LONG);
    }
    mShowingToast.cancel();
    mShowingToast.show();   // 会发现cancel之后调用show是show不出来的
}    

上面这种方式会发现Toast显示不出来,改下写法也许读者能猜到为什么

private Toast mShowingToast;
// 主线程的Handler对象
private Handler mHandler = new Handler(Looper.getMainLooper());
private void showTestToast() {
    // mActivity是一个Activity对象,弹Toast一般用Activity类型的Context
    if (mShowingToast == null) {
        mShowingToast = Toast.makeText(mActivity, "要显示的提示", Toast.LENGTH_LONG);
    }
    mShowingToast.cancel();
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mShowingToast.show();   // 会发现延迟之后就显示出来了
        }
    }, 200);  // 这个时间是自己拍脑袋写的,不影响体验就好,试过使用post也不行
}

为什么呢?可能是同步异步的问题,有可能show操作被后续执行的cancel给覆盖了,所以不生效,看了下源码也没具体看出来

/**
* Show the view for the specified duration.
*/
public void show() {
    if (mNextView == null) {
        throw new RuntimeException("setView must have been called");
    }

    INotificationManager service = getService();
    String pkg = mContext.getOpPackageName();
    TN tn = mTN;
    tn.mNextView = mNextView;

    try {
        service.enqueueToast(pkg, tn, mDuration);
    } catch (RemoteException e) {
        // Empty
    }
}

/**
 * Close the view if it's showing, or don't show it if it isn't showing yet.
 * You do not normally have to call this.  Normally view will disappear on its own
 * after the appropriate duration.
 */
public void cancel() {
    mTN.hide();

    try {
        getService().cancelToast(mContext.getPackageName(), mTN);
    } catch (RemoteException e) {
        // Empty
    }
}

这是Toast内部内TN的一个方法

/**
 * schedule handleHide into the right thread
 */
@Override
public void hide() {
    if (localLOGV) Log.v(TAG, "HIDE: " + this);
    mHandler.post(mHide);
}

如果有读者知道上述问题的原因,欢迎回帖

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏项勇

笔记39 | 数据存储之SharedPreferences的介绍及使用

1524
来自专栏酷玩时刻

微信、支付宝App支付-JPay0.0.2发布JPay

对微信App支付、支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调

1254
来自专栏听雨堂

Android新手之旅(3) 信息的输出

  不管什么语言,了解信息的输出可谓紧要的事情,如vb的msgbox,js的alert,c#的MessageBox.Show,这个对于调试意义重大。Androi...

22710
来自专栏向治洪

开源库BaseRecyclerViewAdapterHelper

相信大家RecyclerView应该不会陌生,大多数开发者应该都使用上它了,它也是google推荐替换ListView的控件,但是用过它的同学应该都知道它在某些...

3016
来自专栏向治洪

ViewPagerIndicator+viewpager指示器详解

前几天学习了ViewPager作为引导页和Tab的使用方法。后来也有根据不同的使用情况改用Fragment作为Tab的情况,以及ViewPager结合Fragm...

1.1K9
来自专栏androidBlog

常用的自定义View例子三(MultiInterfaceView多界面处理)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

741
来自专栏分享达人秀

探究Fragment生命周期

一个Activity可以同时组合多个Fragment,一个Fragment也可被多个Activity 复用。Fragment可以响应自己的输入事件,并拥有...

3344
来自专栏何俊林

Android View框架总结(七)View事件分发机制

View布局告一段落,从本篇开始View事件相关分析,今天分析的是View的事件分发机制 View 事件的分发机制 dispatchTouchEvent onI...

2109
来自专栏james大数据架构

Android中BroadcastReceiver广播

BroadCastReceiver 简介 广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用...

2245
来自专栏向治洪

android几种常见的启动模式

launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和...

2046

扫码关注云+社区

领取腾讯云代金券