持久的Toast消息:执行后Toast不会消失

7

我有一个Toast消息,在执行后不会消失。我猜想这可能与它在循环中有关,但我不确定。有人可以帮助我弄清楚为什么Toast消息不会消失吗?

 @Override
public void onClick(View v) {
    int index = 0;
    for(int i= 0; i<userArray.length; i++){
        if(email.getText().toString().equals(userArray[i])){
            index = i;
        }
        if(passArray[index].equals(password.getText().toString())){
            Toast.makeText(getBaseContext(), "SUCCESS!", Toast.LENGTH_SHORT).show();

        } else {
            Toast.makeText(getBaseContext(), "INVALID LOGIN", Toast.LENGTH_SHORT).show();
        }
    }
    Intent mainIntent = new Intent(LoginActivity.this, MainActivity.class);
    startActivityForResult(mainIntent, 0);
}

}


应该将你的代码放在一个 while 循环中。 - Hoan Nguyen
10个回答

16

如果你从一个 Service 线程中调用 Toast 消息,而该线程在 Toast 消息消失之前完成了工作,那么 Toast 消息可能会被卡住。此时,你将一直看到该 Toast 消息直到你杀掉应用程序。


1
我认为最好、最简单的解决方案是将其发送到当前活动的 UI 线程上运行...类似于:mainActivity.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(mainActivity, message, Toast.LENGTH_SHORT).show(); } }); - roy650

4

Toast不总是会消失。

如果你从服务线程调用它,并且该线程在Toast消失之前完成工作,那么你将无法摆脱Toast消息,直到你杀死应用程序。

(摘自原始回答Jonathan Cole,不幸被删除了)


以下是一个示例堆栈跟踪,解释了该情况如何发生:
  java.lang.IllegalStateException: Handler (android.os.Handler) {123f93ea} sending message to a Handler on a dead thread
      at android.os.MessageQueue.enqueueMessage(MessageQueue.java:325)
      at android.os.Handler.enqueueMessage(Handler.java:631)
      at android.os.Handler.sendMessageAtTime(Handler.java:600)
      at android.os.Handler.sendMessageDelayed(Handler.java:570)
      at android.os.Handler.post(Handler.java:326)
      at android.widget.Toast$TN.hide(Toast.java:387)
      at android.widget.Toast.cancel(Toast.java:133)

3

Toast总是会消失。一定会消失。

因此,您需要显示多个Toast消息。可以通过更改消息并使用某种计数器或在初始消息被显示后禁用来测试此功能。

请注意,相当多的Toast消息可能会堆叠起来,需要很长时间才能连续显示完毕。只要您的应用程序没有无限循环,它们最终会消失。

编辑:我被纠正了。显然,如果从Thread、Service或IntentService启动,Toast消息可能会卡住并保持显示状态。感谢@Johnathan和@zapotec。


16
我需要提醒的是,Toast不一定会消失。如果你在一个服务线程中调用它,并且该线程在Toast消失之前完成了工作,你将无法摆脱屏幕上的Toast消息,直到你关闭应用。 - Jonathan Cole
5
乔纳森·科尔是正确的。如果你在一个线程、服务、IntentService中运行Toast,并且它在Toast消失之前就完成了,那么Toast就不会消失...... - zapotec
那么,有人知道如何去除它吗?有没有一个操作系统技巧可以让用户这么做,因为应用程序找不到在垃圾回收器中的服务链接。--我从用户的角度看待这个问题,屏幕上有一个无法消失的弹框。 - SMBiggs

2

有一些奇怪的情况下,Toast不会消失。 为了处理这个问题,只需要使用Handler。将其创建为一个字段,并在其中使用“post(Runnable)”来显示Toast。


代码示例:uiHandler.post(new Runnable() { @Override public void run() { Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show(); } }); 翻译: - ericharlow

1

这是我的解决方案,使用自定义的提示处理程序。在我的应用程序中完美运行。

public class CustomToast {

    private LayoutInflater inflater;
    private Toast toast;
    private View customToastLayout;
    private TextView LblCustomToast;

    public CustomToast() {}

    public void showCustomToast(String toastMessage, int toastLength, AppCompatActivity context) {

        if(inflater == null) {inflater = context.getLayoutInflater();}
        if(customToastLayout == null) {customToastLayout = inflater.inflate(R.layout.toast_layout, (ViewGroup) context.findViewById(R.id.toast_layout_root));}
        if(LblCustomToast == null) {LblCustomToast = (TextView) customToastLayout.findViewById(R.id.LblCustomToast);}
        LblCustomToast.setText(toastMessage);
        if(toast == null) {toast = new Toast(context);}
        toast.setGravity(Gravity.CENTER_VERTICAL| Gravity.BOTTOM, 0, DPDensity.getPxFromDP(160, context.getResources()));
        toast.setDuration(toastLength);
        toast.setView(customToastLayout);
        if(toast.getView().isShown()) {toast.cancel();}//Toast is cancelled here if currently showing
        toast.show();

    }

}

这是XML布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toast_layout_root"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingLeft="15dp"
    android:paddingTop="5dp"
    android:paddingRight="15dp"
    android:paddingBottom="5dp"
    android:orientation="vertical"
    android:background="@drawable/custom_toast_bg"
    android:gravity="bottom|center"
    android:layout_marginBottom="50dp">

    <TextView android:id="@+id/LblCustomToast"
        android:text="Test"
        android:textSize="16dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/lightLime"
        android:layout_gravity="center"
        android:gravity="center"/>

</LinearLayout>

这里是使用方法:

customToast = new CustomToast();
customToast.showCustomToast(getString(R.string.your_message), Toast.LENGTH_SHORT, (AppCompatActivity) mainActivityContext);

1
我曾经遇到过这个问题。我发现,我实例化了超过10个toast。每个toast都等待前一个淡出后再显示下一个,总共在屏幕上停留了20秒。
我发现将所有的toast存储在ArrayList中,然后取消它们可以解决我的问题。
private ArrayList<Toast> toasts;
public void sendToast(final String message) {
    if (null == toasts) {
        toasts = new ArrayList<Toast>();
    }
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            try {
                Toast toast = Toast.makeText(NJActivity.this, message, Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.TOP|Gravity.CENTER, 0, 300);
                toast.show();
                toasts.add(toast);
            } catch(Exception e) {/* do nothing, just means that the activity doesn't exist anymore*/}
        }
    });
}


public void removeToast() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (null != toasts) {
                for(Toast toast:toasts) {
                    toast.cancel();
                }
                toasts = null;
            }
        }
    });     
}

然后在 destroy 和 stop 事件中,我调用了 removeToast() 方法。

@Override
public void onDestroy() {
    super.onDestroy();
    removeToast();
}

@Override
protected void onStop () {
    super.onStop();
    removeToast();
}

为什么这个回答被踩了?我觉得这个解决方案很有趣啊。 - SMBiggs

0

我以前也遇到过同样的问题,以下是帮助我的方法。我在onCreate中创建了我的Toast,就像这样:

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sample);

    Context context = getApplicationContext();
    CharSequence text = "~I'm a toast that will dissapear~!";
    int duration = Toast.LENGTH_SHORT;
    Toast toast = Toast.makeText(context, text, duration);
    toast.setGravity(Gravity.TOP, 0, 0);}

然后我只需从在不同线程上运行的方法中调用它即可。

toast.show();

希望能对你有所帮助!

另外,我认为问题可能是你的 Toast 在一个线程上创建,而在另一个(UI 线程)上调用了它。


-1
  I m guessing it has something to do with it being in the loop but I'm not sure.

是的,你说得对,它出现是因为你将它放在了 for 循环中,所以循环执行的次数越多,Toast 就会出现多少次。

你在代码中多次显示了 Toast。

如果你不想要多个 Toast,最好在 for 循环外面写。


-1

我认为问题是屏幕上一遍又一遍出现了 Toast,而且消失的时间很长。请将 Toast 放在循环外部并检查条件是否多次成立。简而言之,只需对代码进行 DEBUG


-1

Toast会停留更长时间。一旦生成,它将永远消失。 由于在循环中它们不断地相互生成,所以它给你一种一直存在的错觉。 如果你耐心等待一段时间,所有东西都会在一段时间后消失。

如果你想显示成功信息。

尝试制作alert dialogue并在某个Text View上不断更新消息,以显示你想要在成功和失败时显示的成功消息。

或者只有在登录失败时才尝试提醒Toast

或者如果你想坚持同样的方法,请检查Infintie Loop


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接