Закінчіть стару діяльність і починайте нову або навпаки


80

Я знаю, що я отримую однаковий результат з обома фрагментами коду

finish();
startActivity(newActivity);

і

startActivity(newActivity);
finish();

Я хотів би знати вашу думку, якщо між ними є велика різниця. Чи один кращий за інший? Якщо так, то чому?

Відповіді:


61

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


1
це звучить і для мене розумно
Тима

6
Анімація у мене інша. Дивіться мою відповідь нижче.
Монсьє,

але підхід просто повністю НЕПРАВИЛЬНИЙ. Існують прапори (для наміру, а також у маніфесті), які насправді існують для цього випадку використання.
Ewoks,

@Ewoks, будь ласка, ідіть головою, що значить, які прапори?
Ентоні

3
Насправді є велика різниця у поведінці завдань програми. Я розробив це питання в окремій відповіді.
Віт Худенко

27

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


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 для: Намір {cmp = com.foo.bar / com.foo.bar.MainActivity}

І це переломний момент, з якого (за певних умов) справа може піти не так.

Підводячи підсумок, якщо ви хочете бути в безпеці (а не відчувати несподівані побічні ефекти того, FLAG_ACTIVITY_NEW_TASKщо додається до наміру), тоді порядок повинен бути таким:

  • startActivity()
  • finish()

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

Записи екрану:


Переглядаючи вихідний код, Activity.startActivity () в кінцевому рахунку викликає ActivityThread.sendActivityResult (), який, у свою чергу, викликає scheduleSendResult (), який просто додає активність до черги. Потік обробить його пізніше. З іншого боку, END () викликає ActivityManagerNative.finishActivity (), який негайно закінчує діяльність.
Еммануель

@ Еммануель, я не можу з'ясувати, чи стосується ваша заява проблеми, яку я описав. :)
Віт Худенко

9

На додаток до відповіді Еммануелів:

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


7

Я б зробив другий вибір, я не підтримую це ні на чому, що я шукав з офіційних джерел, але, є більше сенсу запустити нову активність до того, як ви зателефонуєте закінчити, таким чином, нова діяльність з’являється через намір , а тепер фонова діяльність може викликати всі її методи очищення.

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

Сподіваюся, ви розумієте, що я намагаюся заявити, я зробив би другий варіант, аби перестрахуватися.


Так, я зрозумів вашу ідею. Це звучить логічно. Але я не уявляю себе, коли така ситуація може бути можливою
Тима

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! але у другому випадку все відбувається нормально.


Коли ви закінчуєте () додаток, андроїд витягує активність LRU зі стеку, який є В. Також, що змушує мене думати, що finish () є негайним і не асинхронним.
Mehmet AVŞAR

0

Зазвичай я це роблю startActivity()раніше, finish()оскільки думаю, що це переконається, що новий екран з’явиться до того, як вийде попередній.

У моєму додатку є сторінка входу. Після успішного входу користувача дія входу зникне, а основна активність закінчиться. Це чудово працює в Android 4.

Сьогодні я хотів переписати його в Material design. Однак у мене виникла велика проблема. Нова студія 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.

Я змінив порядок, і тепер він працює без помилок на моєму телефоні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.