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

1

5

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.

Rush answered 25/10, 2019 at 10:33 Comment(11)
toasts can show outside of the app, it will cycle to toast 20 becasue its stored in memory eventhough you called a on destroy....What do you exactly want to achieve with the toast cycle? you can also put a if statement and take your code and say yourcode if ondestroy toast.cancelEniwetok
Actually, this code isn't running anymore when the Activity is destroyed. However, since you don't put a delay between your Toasts, they all stack up to 20 and then the Activity is destroyed. By that time, the delay during which the Toast is supposed to be displayed isn't over yet, so it will still appear.Whitby
Arthur explained it better than meEniwetok
@RubenMeiring I am not creating anything with these toasts. I was just curious to know that how my code can render toast on homepage[home screen of mobile]Rush
@ArthurAttout Ok, it stakes the Toast. But how can my code render toast on homepage? Main Thread of app is gone? or not?Rush
Because the toasts are saved in the memory and the toast is not a APP function its an OS function..or well thats my understanding don;t think i am explaining it correctlyEniwetok
There is no main thread per app, but rather just a Main Thread for the whole GUI. When you request in your app to show a Toast, this request is handed to Android's Main Thread, and it displays it. When you kill your app, this Main Thread isn't killed aswell (otherwise your whole phone would be unresponsive). This Main Thread still has Toasts to show, they are just stacked up.Whitby
@ArthurAttout it is always taught that there is main thread per app. Well, after this comment I have lots of questions now. Can you refer any documentation or blog to study this?Rush
Let me correct myself : your App also has a Main Thread, but that's not the one that handles Toasts.Whitby
@ArthurAttout so, are there two threads when I launch the app? Android system thread and app's Main thread? Confused.Rush
That's how it works. Check out the official doc for further information.Whitby
M
6

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
    }
}
Maura answered 25/10, 2019 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.