7

I have a toast message that doesn't disappear after execution. Im guessing it has something to do with it being in the loop but I'm not sure. Can someone help me figure out what why the toast message doesn't disparate?

 @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);
}

}

cApple
  • 313
  • 1
  • 7
  • 20

10 Answers10

16

A Toast message can become stuck if you call it from a Service thread and that thread completes it's work before Toast is set to disappear. You are then stuck with the Toast message on the screen until you kill the app.

Matt
  • 74,352
  • 26
  • 153
  • 180
Jonathan Cole
  • 191
  • 1
  • 4
  • 1
    Best and simplest solution for my was to send it to run on the current activity's UI thread... something like: mainActivity.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(mainActivity, message, Toast.LENGTH_SHORT).show(); } }); – roy650 Feb 08 '17 at 21:15
4

A Toast does not always disappear.

"If you call it from a Service thread and that thread completes it's work before Toast is set to disappear, you are stuck with the Toast message on the screen until you kill the app."

(copied from original answer by Jonathan Cole, which was unfortunately removed)


Here is a sample stack trace that explains how the situation can occur:

  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)
Community
  • 1
  • 1
Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
3

Toast always disappears. Always.

Therefore, you are displaying multiple Toast messages. Guaranteed. Test this by changing the messages with some sort of counter or disabling after the initial one is displayed.

Note that quite a few Toasts can stack up and take a loooooong time to finish showing back-to-back. Wait and they will eventually go away as long as your app isn't looping indefinitely.

Edit: I stant corrected. Apparently, Toast messages can get stuck and remain displayed if started from a Thread, Service, or IntentService. Thank you @Johnathan and @zapotec.

David Manpearl
  • 12,362
  • 8
  • 55
  • 72
  • 16
    I would add that Toast does not Always disappear. If you call it from a Service thread and that thread completes it's work before Toast is set to disappear, you are stuck with the Toast message on the screen until you kill the app. – Jonathan Cole Oct 30 '13 at 23:15
  • 5
    Jonathan Cole is right. If you run the Toast inside a Thread, Service, IntentService and it finishes before the Toast disappears, it won't disappears..... – zapotec Nov 25 '14 at 10:04
  • So, does anyone know how to remove it? Is there an OS technique that the user can do, because there is no way the app can find the link to the Service that is in the garbage collector. --I'm looking at this from a user's perspective with a toast on the screen that won't go away. – SMBiggs Jun 20 '17 at 15:49
2

There are some weird cases that the toast won't disappear. In order to handle this, just use the Handler. Create one as a field, and use "post(Runnable)" with the toast being shown there.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • code example: ```uiHandler.post(new Runnable() { @Override public void run() { Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show(); } });``` – ericharlow Jul 13 '16 at 00:07
1

I had this problem. What I found is that I instantiated over 10 toasts. Each waited till the next one faded before displaying the next, with a total 20 seconds on screen.

I found that storing all toasts in an arraylist, then canceling them all fix my problem.

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;
            }
        }
    });     
}

Then on destroy on stop I called the removeToast() method

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

@Override
protected void onStop () {
    super.onStop();
    removeToast();
}
Gplex314159
  • 210
  • 2
  • 4
1

Here’s my solution with a custom toast handler. Works perfectly in m app.

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();

    }

}

Here is the XML Layout

<?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>

And here is the Usage:

customToast = new CustomToast();
customToast.showCustomToast(getString(R.string.your_message), Toast.LENGTH_SHORT, (AppCompatActivity) mainActivityContext);
user2288580
  • 2,210
  • 23
  • 16
0

I had same problem before and here is what helped me. I created my Toast in onCreate, like this

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);}

And then I simply called it from methods that run on the different thread as

toast.show();

I hope it can help!

P.S. I think the problem was that your toast was created on one thread and called from another (uithread)

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

Yes you are right its appearing beacause you have kept it in for loop so as many times the loop will execute that many time the Toast will appear.

You are showing the Toast multiple times in your code.

I would be better if your don't want toast multiple times then you can write it out side the for loop.

GrIsHu
  • 29,068
  • 10
  • 64
  • 102
-1

I think the issue is toast is appearing again and again on screen and its taking the time to dismiss. Check your code bye putting the toast outside loop and also check if the conditions are true multiple times. In short just DEBUG your code.

Sanober Malik
  • 2,765
  • 23
  • 30
-1

Toast stays a little longer. It will always disappear once generated. As in loop they are getting continuously generated upon each other, so its giving you the illusion of being there always. if you will remain patient and wait for a little long all will disappear after some time.

If you want to show success message.

Try making alert dialogue and keep on updating message their on some Text View the success message that you want to show on success and failure.

or try raising Toast only when it fails to login.

Or check for Infintie Loop if you want to stick to the same approach

DeltaCap019
  • 6,532
  • 3
  • 48
  • 70