zoukankan      html  css  js  c++  java
  • 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);
    }

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

    参考文章:

    http://blog.csdn.net/goodding/article/details/8792628

    http://blog.csdn.net/arui319/article/details/7022392

  • 相关阅读:
    tftp服务器
    iw工具的使用
    六、【ioctl】应用程序和驱动程序中的ioctl
    位反转现象(Bit Flip)
    openwrt有线网卡的停用与开启
    寒假小记
    ARMLinux汇编到ADS汇编转换需要注意的问题
    c function pointer example
    (转)解决mysql“Access denied for user 'root'@'localhost'”
    c语言 面向对象的栈
  • 原文地址:https://www.cnblogs.com/popfisher/p/5631243.html
Copyright © 2011-2022 走看看