Вопрос

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

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

в 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);
Это было полезно?

Решение

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

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

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

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

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

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

Другие советы

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

Раздел «singleTop» http://developer.android.com/guide/comComponents/tasks-and-back-stack.html ясно объясняет, как это работает (обратите внимание на жирный текст ниже;Я также доказал это посредством собственной отладки):

«Например, предположим, что задний стек задачи состоит из корневого действия A с действиями B, C и D сверху (стек ABCD;Д наверху).Приходит намерение на действие типа D.Если D имеет «стандартный» режим запуска по умолчанию, запускается новый экземпляр класса, и стек становится A-B-C-D-D.Однако если режим запуска D — «singleTop», существующий экземпляр D получает намерение через onNewIntent(), поскольку он находится на вершине стека — стек остается A-B-C-D.Однако, если поступает интент для активности типа 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 — предотвратить создание нескольких экземпляров действия.Например, когда это действие может быть запущено посредством намерения, исходящего извне основной задачи вашего приложения.Я обнаружил, что для внутреннего переключения между действиями в моем приложении обычно мне нужен FLAG_ACTIVITY_REORDER_TO_FRONT.

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

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top