为什么即使在应用程序调用 onDestroy() 时 Toast 仍然显示?

Mak*_*and 5 android android-toast

假设我有这个代码 onCreate()

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

当我启动应用程序时,Toasts 开始弹出。

现在,当我按下后退按钮时(假设在 Toast 5 之后)。在onDestroy()被调用时,应用程序被关闭。

但是我仍然可以看到 Toast 弹出,直到它达到 20 或者我从内存中清除应用程序。

题:

为什么我的代码用完了应用程序?

我已经给出了我的活动的上下文,那么它不应该在活动被破坏后立即停止吗?

不是context这里的问题吗?

如果您链接任何文档,将会很有帮助。

Ris*_*wan 5

Toast类中,Toast.makeText()是静态的method。当您调用此方法时,将Toast创建一个新对象并将您传递的对象Context保存在其中,系统的默认布局用于创建一个view附加到您的Toast对象的对象,并且还设置了重力来管理您toast将在屏幕上显示的位置。

toast的由系统服务显示。该服务维护一个queuetoast messages被显示,并显示使用其自己的他们Thread。当您调用show()您的toast objectthen 时,它会将您排入toast系统服务的消息队列中。因此,当您activity在创建后被销毁时20 toast,系统服务已经开始行动并且其中有消息message queue要显示。通过回按您的activity(销毁时)系统不能得出您可能不打算显示剩余的 toast 消息的结论。只有当您从内存中清除您的应用程序时,系统才能自信地推断它不再需要toast message从您的应用程序中显示。

有关更多信息,您可以查看Toast class. 我为您提供了相关方法。顺便说一句好问题

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;
}
Run Code Online (Sandbox Code Playgroud)

创建新 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);
}
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)