Завершите старую деятельность и начните новую или наоборот

80

Я знаю, что получаю одинаковый результат с обоими фрагментами кода

finish();
startActivity(newActivity);

и

startActivity(newActivity);
finish();

Хотелось бы узнать ваше мнение, если между ними есть большая разница. Одно лучше другого? Если да, то почему?

Тима
источник

Ответы:

61

Когда вы выполняете startActivity (), все, что вам нужно, - это разместить ваше намерение в очереди событий. Фактический запуск активности происходит асинхронно в ближайшем будущем. Так что я не вижу большой разницы между ними.

Эммануэль
источник
1
для меня это тоже звучит разумно
Тима
6
Анимация у меня другая. Смотрите мой ответ ниже.
Monstieur
но подход совершенно НЕПРАВИЛЬНЫЙ .. Существуют флаги (для намерения, а также в манифесте), которые действительно существуют для этих вариантов использования.
Ewoks
@Ewoks, пожалуйста, идите, что значит, какие флаги?
Энтони
3
На самом деле существует большая разница в поведении задач приложения. Я подробно остановился на этом вопросе.
Вит Худенко
27

Анимация явно другая (по крайней мере, на 4.1 и далее). При finish()первом вызове начинает исчезать первое действие раньше, и вы можете ненадолго увидеть черный фон, прежде чем исчезнет новое действие. При startActivity()первом вызове новое действие исчезает поверх старого, и черный фон не виден.

Monstieur
источник
16

Существует важное различие в поведении задач приложения в зависимости от порядка startActivity()и finish()вызовов.

Случай, который я описываю, относится только к ситуации, когда текущее действие (то, которое останавливается) является единственным в задаче.

Обычно можно ожидать, что начальное намерение (созданное вами намерение начать другое действие) не изменяется системой. И это не тот случай, если finish()вызывается последнее действие в задаче перед вызовом startActivity().

В этом случае ActivityManager, системный компонент, при выполнении флага startActivity() добавляет Intent.FLAG_ACTIVITY_NEW_TASK к вашему намерению.

Когда это происходит, можно заметить запись журнала в LogCat, подобную этой:

W / ActivityManager: startActivity вызывается после завершения ActivityRecord {4a19b47 u0 com.foo.bar/com.foo.bar.SplashActivity t4928 f}; принудительное использование Intent.FLAG_ACTIVITY_NEW_TASK для: Intent {cmp = com.foo.bar / com.foo.bar.MainActivity}

И это поворотный момент, после которого (при определенных условиях) что-то может пойти не так.

Подводя итог, если вы хотите быть в безопасности (вместо того, чтобы испытывать неожиданные побочные эффекты от FLAG_ACTIVITY_NEW_TASKдобавления к намерению), то порядок должен быть следующим:

  • startActivity()
  • finish()

Демо- проект .

Записи с экрана:

Вит Худенко
источник
Глядя на исходный код, Activity.startActivity () в конечном итоге вызывает ActivityThread.sendActivityResult (), который, в свою очередь, вызывает scheduleSendResult (), который просто добавляет действие в очередь. Поток обработает его позже. С другой стороны, finish () вызывает ActivityManagerNative.finishActivity (), который сразу же завершает действие.
Эммануэль
@Emmanuel, я не могу понять, относится ли ваше заявление к описанной мною проблеме. :)
Вит Худенко
9

В дополнение к ответу Эммануэля:

Оба метода startActivityи finishбудут запланированы после завершения вызывающего метода, поскольку оба обрабатываются потоком пользовательского интерфейса.

Scheffield
источник
7

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

Если бы вы сделали наоборот, возможно, у намерения не было времени сработать до того, как очистка будет завершена. Т.е. будет ли операция вызывать startActivity () после вызова finish ()?

Надеюсь, вы понимаете, о чем я пытаюсь заявить, я бы выбрал второй вариант на всякий случай.

слепой
источник
Да, я понял вашу идею. Звучит логично. Но я не могу представить себя, когда такая ситуация могла бы быть возможна
Тима
2

У меня была аналогичная проблема:

Activity A: singleInstance
Activity B: singleInstance
Activity C: singleInstance

A starts B 
B starts C
C wants to start A:

здесь, если я использую:

finish();
startActivity(A);

происходит нечто связное: на передний план выходит действие B вместо A! но если я изменю код следующим образом:

startActivity(A);
finish();

все в порядке, и действие А становится видимым.

Я не знаю, в чем проблема, но кажется, что в первом случае C завершает работу до выполнения команды startActivity, так что задний стек обрабатывает ситуацию и показывает свою главную активность, которая является B! но во втором случае все происходит нормально.

узкий
источник
Когда вы finish () приложение, android извлекает активность LRU из стека, которая равна B. Кроме того, я думаю, что finish () выполняется немедленно, а не асинхронно.
Mehmet AVŞAR
0

Я обычно делаю это startActivity()раньше, finish()поскольку думаю, что это обеспечит появление нового экрана до того, как погаснет предыдущий.

В моем приложении есть страница входа. После успешного входа пользователя активность входа прекращается, а основная активность продолжается. Он отлично работает в Android 4.

Сегодня я хотел переписать его в материальном дизайне. Однако у меня возникла большая проблема. Новая студия Android создает пустую активность с материальным дизайном, что, как мне кажется, требует много ресурсов. Тот же процесс, но я получил ошибку

11-26 18:20:44.450 18397-18397/? I/Choreographer: Skipped 42 frames!  The application may be doing too much work on its main thread.
11-26 18:20:44.485 18397-18408/? I/art: Background partial concurrent mark sweep GC freed 2864(191KB) AllocSpace objects, 4(43MB) LOS objects, 13% free, 100MB/116MB, paused 8.056ms total 39.767ms

Он сказал, что мои приложения mainActivityтребуют много ресурсов при запуске в моем телефонном журнале. У меня нет ничего, кроме mainActivityтого, что это макет Material Design по умолчанию.

Я поменял порядок, и теперь он работает без ошибок на моем телефоне.

в шляпе
источник