Подтвердить что ты не робот

Режим запуска "single top" для Android и onNewIntent

В документации для Android я прочитал, что, установив свойство ActivityMode Activity в singleTop OR, добавив флаг FLAG_ACTIVITY_SINGLE_TOP к моему намерению, вызов startActivity(intent) будет повторно использовать один экземпляр Activity и дать мне Intent в onNewIntent обратный вызов. Я делал обе эти вещи, и onNewIntent никогда не срабатывает, и onCreate срабатывает каждый раз. В документах также указано, что this.getIntent() возвращает намерение, которое было впервые передано в действие, когда оно было впервые создано. В onCreate я звоню getIntent, и каждый раз получаю новый (я создаю объект намерения в другом действии и добавляю к нему дополнительный файл... это лишнее должно быть одинаковым каждый раз, если он возвращал мне тот же объект намерения). Все это заставляет меня поверить, что моя деятельность не действует как "единственная вершина", и я не понимаю, почему.

Чтобы добавить некоторый фон в случае, если я просто пропустил требуемый шаг, вот объявление активности в манифесте и код, который я использую для запуска этой операции. Сама деятельность не делает ничего, что стоит упомянуть в отношении этого:

в AndroidManifest.xml:

    <activity
        android:name=".ArtistActivity"
        android:label="Artist"
        android:launchMode="singleTop">
    </activity>     

в моей вызывающей деятельности:

        Intent i = new Intent();
        i.putExtra(EXTRA_KEY_ARTIST, id);
        i.setClass(this, ArtistActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(i);
4b9b3361

Ответ 1

Вы проверяли, был ли вызван onDestroy()? Вероятно, почему onCreate() вызывается каждый раз вместо onNewIntent(), который вызывается только в том случае, если активность уже существует.

Например, если вы оставите свою активность с помощью кнопки BACK, она по умолчанию будет уничтожена. Но если вы поднимаетесь выше в стеке действий в другие действия и оттуда снова вызываете свой ArtistActivity.class, он пропустит onCreate() и перейдет непосредственно к onNewIntent(), потому что действие уже создано и поскольку вы определили его как singleTop Android не создаст новый экземпляр, а возьмет тот, который уже лежит.

Что я делаю, чтобы понять, что происходит Я реализую фиктивные функции для всех разных состояний каждого действия, поэтому я всегда начинаю:

@Override
public void onDestroy() {
    Log.i(TAG, "onDestroy()");
    super.onDestroy();
}

То же самое для onRestart(), onStart(), onResume(), onPause(), onDestroy()

Если приведенная выше (кнопка BACK) не была вашей проблемой, реализация этих манекенов по крайней мере поможет вам немного отладить ее.

Ответ 2

Принятый ответ не совсем корректен. Если onDestroy() был вызван ранее, тогда да, onCreate() всегда будет вызываться. Однако это утверждение неверно: "Если вы поднимаетесь выше по стеку действий в другие действия и оттуда снова вызываете свой ArtistActivity.class, он будет пропускать onCreate() и перейти непосредственно к onNewIntent()"

В разделе "singleTop" http://developer.android.com/guide/components/tasks-and-back-stack.html объясняется, как это работает (внимание к жирным текстам ниже, я также доказал это с помощью собственной отладки):

"Например, предположим, что стек назад задачи состоит из корневой активности A с действиями B, C и D сверху (стек ABCD; D находится сверху). активность типа D. Если D имеет стандартный режим запуска по умолчанию, запускается новый экземпляр класса, и стек становится ABCDD. Однако, если режим запуска D является "singleTop", существующий экземпляр D получает намерение через onNewIntent(), потому что он находится в верхней части стека - стек остается ABCD. Однако , если намерение прибывает для активности типа B, тогда в стек добавляется новый экземпляр B, даже если его режим запуска - "singleTop".

Другими словами, запуск активности через SINGLE_TOP будет только повторно использовать существующее действие, если оно уже находится в верхней части стека. Он не будет работать, если другое действие в той же самой задаче находится наверху (например, действие, выполняющее startActivity (SINGLE_TOP)); вместо этого будет создан новый экземпляр.

Вот два способа исправить это, чтобы вы получили поведение SINGLE_TOP, которое вам нужно, - общая цель которого заключается в повторном использовании существующего действия вместо создания нового...

Первый способ (как описано в разделе комментариев принятого  ответ): Вы можете добавить в свою активность запуск режима "singleTask". Это заставит onNewIntent(), потому что singleTask означает, что может быть только один экземпляр определенного действия в заданной задаче. Это несколько хакерское решение, хотя, если ваше приложение нуждается в нескольких экземплярах этой активности в конкретной ситуации (например, я делаю для своего проекта), вы ввернуты.

Второй способ (лучше): Вместо FLAG_ACTIVITY_SINGLE_TOP используйте FLAG_ACTIVITY_REORDER_TO_FRONT. Это приведет к повторному использованию существующего экземпляра активности, переместив его в начало стека (onNewIntent() будет вызываться как ожидалось).

Основной целью FLAG_ACTIVITY_SINGLE_TOP является предотвращение создания нескольких экземпляров Activity. Например, когда эта деятельность может быть запущена с помощью намерения, которое приходит из-за пределов основной задачи вашего приложения. Для внутреннего переключения между действиями в моем приложении я обнаружил, что FLAG_ACTIVITY_REORDER_TO_FRONT обычно является тем, что я хочу.

Ответ 3

Установите этот флаг в свои намерения:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)