【问题标题】:Why Toast keeps showing even when the app called onDestroy()?为什么即使应用程序调用了 onDestroy(),Toast 仍然显示?
【发布时间】:2020-02-21 17:00:30
【问题描述】:

假设我在onCreate() 中有这段代码

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

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

现在,当我按下返回按钮时(比如说在 Toast 5 之后)。 onDestroy() 被调用,应用关闭。

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

问题:

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

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

context 在这里不重要吗?

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

【问题讨论】:

  • toasts 可以在应用程序之外显示,它会循环到 toast 20,因为它存储在内存中,即使你调用了 on destroy ......你到底想用 toast 循环实现什么?你也可以放一个 if 语句,然后把你的代码说成 yourcode if ondestroy toast.cancel
  • 实际上,当Activity被销毁时,这段代码就不再运行了。但是,由于您没有在 Toast 之间设置延迟,因此它们都堆叠到 20 个 然后 Activity 被销毁。到那时,应该显示 Toast 的延迟还没有结束,所以它仍然会出现。
  • 亚瑟解释得比我好
  • @RubenMeiring 我没有用这些吐司创造任何东西。我只是想知道我的代码如何在主页[移动主屏幕]上呈现吐司
  • @ArthurAttout 好的,它赌上了 Toast。但是我的代码如何在主页上渲染吐司?应用程序的主线程消失了?还是不行?

标签: android android-toast


【解决方案1】:

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

您的toast 由系统服务显示。此服务维护要显示的toast messagesqueue,并使用自己的Thread 显示它们。当您在toast object 上调用show() 时,它会将您的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;
}

创建新的 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);
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多