Почему Toast отображается, даже когда приложение вызывает onDestroy ()? - PullRequest
4 голосов
/ 25 октября 2019

Допустим, у меня есть этот код в onCreate()

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

, когда я запускаю приложение, всплывают тосты.

сейчас, когда я нажимаю кнопку «назад» (скажем, после тоста 5). Вызывается onDestroy(), приложение закрыто.

Но я все еще вижу всплывающее окно с тостом, пока оно не достигнет 20, или я не уберу приложение из памяти.

Вопрос:

Почему в моем коде заканчивается приложение?

Я дал контекст своей деятельности, не должен ли он остановиться, как только деятельность будет уничтожена?

Разве здесь context не имеет значения?

Было бы полезно, если вы связываете какую-либо документацию.

1 Ответ

4 голосов
/ 25 октября 2019

В Toast классе, Toast.makeText() является статическим method. Когда вы вызываете этот метод, создается новый Toast объект, и в нем сохраняется переданный вами Context, а системный макет по умолчанию используется для создания view, который присоединен к вашему Toast объекту, и гравитация также устанавливается так, чтобыопределяет, где на экране будет отображаться ваш toast.

Ваш toast отображается системной службой. Эта служба поддерживает отображение queue из toast messages и отображает их, используя собственный Thread. Когда вы звоните show() на ваш toast object, он помещает ваш toast в очередь сообщений системной службы. Таким образом, когда ваш activity уничтожается после создания 20 toast, тогда системная служба уже вступила в действие, и в ее message queue есть сообщения для отображения. При обратном нажатии на вашей системе activity (при уничтожении) невозможно сделать вывод, что вы, возможно, не намереваетесь отображать оставшиеся всплывающие сообщения. Только когда вы удаляете свое приложение из памяти, система может уверенно сделать вывод, что ей больше не нужно отображать 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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...