Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Toast keeps showing even when the app called onDestroy()?

Let's say I have this code in onCreate()

   for (int i = 0; i < 20; i++) {
        Toast.makeText(MainActivity.this, "Toast "+i, Toast.LENGTH_SHORT).show();
    }

when I launch the app, Toasts start to pop up.

now, when I press the back button(let's say after Toast 5). The onDestroy() is called, app is closed.

But I can still see the Toast popping up until it reaches to 20 or I clear app from memory.

Question:

Why my code is running out of the app?

I had given the context of my activity, then shouldn't it stop as soon as the activity is destroyed?

Doesn't the context matter here?

It would be helpful if you link any documentation.

like image 364
Makarand Avatar asked Oct 25 '19 10:10

Makarand


People also ask

What method call is used to display a toast notification?

Display the created Toast Message using the show() method of the Toast class. The code to show the Toast message: Toast. makeText(getApplicationContext(), "This a toast message", Toast.

What is the difference between toast and alert dialog?

Toasts are a great way to deliver unobtrusive status messages to users, because unlike Alert Dialogs they do not take focus away from the Activity. They're perfect for displaying notifications that don't need too much attention, for example to tell the user that a download has completed.

What are toast notifications Android?

A toast provides simple feedback about an operation in a small popup. It only fills the amount of space required for the message and the current activity remains visible and interactive. Toasts automatically disappear after a timeout.


1 Answers

In Toast class, Toast.makeText() is a static method. When you call this method a new Toast object is created and your passed Context is saved in it and system's default layout is used to create a view which is attached to your Toast object and gravity is also set that manages where on screen your toast will be displayed.

Your toast is displayed by system service. This service maintains a queue of toast messages to be displayed and displays them using its own Thread. When you call show() on your toast object then it enqueues your toast into the message queue of system service. So when your activity is destroyed after creating 20 toast, then system service has already swung into action and it has messages in its message queue to display. By back press on your activity (on destroy) system cannot conclude that you may not intend to display remaining toast messages. Only when you clear your app from memory, system can confidently infer that it no longer needs to display toast message from your app.

For more information you may look at the source code of Toast class. I am including relevant methods for you. BTW good question 👍🏻

Implementation of Toast.makeText

 /**
 * Make a standard toast to display using the specified looper.
 * If looper is null, Looper.myLooper() is used.
 * @hide
 */
public static Toast makeText(@NonNull Context context, @Nullable Looper looper,
        @NonNull CharSequence text, @Duration int duration) {
    Toast result = new Toast(context, looper);

    LayoutInflater inflate = (LayoutInflater)
            context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
    TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
    tv.setText(text);

    result.mNextView = v;
    result.mDuration = duration;

    return result;
}

Creation of new Toast :

/**
 * Constructs an empty Toast object.  If looper is null, Looper.myLooper() is used.
 * @hide
 */
public Toast(@NonNull Context context, @Nullable Looper looper) {
    mContext = context;  // your passed `context` is saved.
    mTN = new TN(context.getPackageName(), looper);
    mTN.mY = context.getResources().getDimensionPixelSize(
            com.android.internal.R.dimen.toast_y_offset);
    mTN.mGravity = context.getResources().getInteger(
            com.android.internal.R.integer.config_toastDefaultGravity);
}

Implementation of show()

/**
 * 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;
    final int displayId = mContext.getDisplayId();

    try {
        service.enqueueToast(pkg, tn, mDuration, displayId);
    } catch (RemoteException e) {
        // Empty
    }
}
like image 115
Rishabh Dhawan Avatar answered Oct 23 '22 12:10

Rishabh Dhawan