Beenden Sie die alte Aktivität und starten Sie eine neue oder umgekehrt

80

Ich weiß, dass ich mit beiden Codefragmenten das gleiche Ergebnis erhalte

finish();
startActivity(newActivity);

und

startActivity(newActivity);
finish();

Ich würde gerne Ihre Meinung erfahren, wenn es einen großen Unterschied zwischen ihnen gibt. Ist einer besser als der andere? Wenn ja warum?

Tima
quelle

Antworten:

61

Wenn Sie startActivity () ausführen, müssen Sie Ihre Absicht lediglich in einer Warteschlange mit Ereignissen veröffentlichen. Der eigentliche Start der Aktivität erfolgt in naher Zukunft asynchron. Ich sehe also keinen großen Unterschied zwischen den beiden.

Emmanuel
quelle
1
es klingt auch für mich vernünftig
Tima
6
Die Animation ist für mich anders. Siehe meine Antwort unten.
Monstieur
Aber der Ansatz ist einfach völlig FALSCH. Es gibt Flags (sowohl für Absichten als auch für Manifeste), die tatsächlich für diese Anwendungsfälle existieren.
Ewoks
@Ewoks bitte Kopf gehen, was bedeutet, welche Flaggen?
Anthony
3
Es gibt tatsächlich einen großen Unterschied im Verhalten von App-Aufgaben. Ich habe die Angelegenheit in einer separaten Antwort ausgeführt.
Vit Khudenko
27

Die Animation ist deutlich anders (mindestens ab 4.1). Wenn Sie finish()zuerst anrufen , wird die erste Aktivität früher ausgeblendet, und Sie können kurz einen schwarzen Hintergrund sehen, bevor die neue Aktivität eingeblendet wird. Wenn Sie startActivity()zuerst anrufen, wird die neue Aktivität über der alten ausgeblendet, und der schwarze Hintergrund ist nicht sichtbar.

Monstieur
quelle
16

Es gibt einen wichtigen Unterschied in der Anwendung Aufgabe Verhalten in Abhängigkeit von der Reihenfolge startActivity()und finish()Beschwörungen.

Der Fall, den ich beschreibe, ist nur auf die Situation beschränkt, in der die aktuelle Aktivität (die angehaltene) die einzige in der Aufgabe ist.

Normalerweise würden Sie erwarten, dass die Startabsicht (die Absicht, die Sie zum Starten einer anderen Aktivität erstellen) vom System nicht geändert wird. Und das ist nicht der Fall, wenn finish()bei der letzten Aktivität in der Aufgabe vor dem Aufruf aufgerufen wird startActivity().

In diesem Fall der ActivityManager, eine Systemkomponente, während Sie das startActivity() Add- Intent.FLAG_ACTIVITY_NEW_TASK Flag zu Ihrer Absicht ausführen .

In diesem Fall kann es vorkommen, dass im LogCat ein ähnlicher Protokolleintrag angezeigt wird:

W / ActivityManager: startActivity wird nach Abschluss von ActivityRecord aufgerufen {4a19b47 u0 com.foo.bar/com.foo.bar.SplashActivity t4928 f}; Erzwingen von Intent.FLAG_ACTIVITY_NEW_TASK für: Intent {cmp = com.foo.bar / com.foo.bar.MainActivity}

Und dies ist der Wendepunkt, von dem aus (unter bestimmten Umständen) etwas schief gehen kann.

Zusammenfassend FLAG_ACTIVITY_NEW_TASKmuss die Reihenfolge wie folgt lauten: Wenn Sie auf der sicheren Seite sein möchten (anstatt unerwartete Nebenwirkungen des Hinzufügens zur Absicht zu erleben ):

  • startActivity()
  • finish()

Demo- Projekt .

Bildschirmaufnahmen:

Vit Khudenko
quelle
Mit Blick auf den Quellcode ruft Activity.startActivity () letztendlich ActivityThread.sendActivityResult () auf, das wiederum ScheduleSendResult () aufruft, das die Aktivität nur einer Warteschlange hinzufügt. Ein Thread wird es später verarbeiten. Auf der anderen Seite ruft finish () ActivityManagerNative.finishActivity () auf, wodurch die Aktivität sofort beendet wird.
Emmanuel
@Emmanuel, ich kann nicht herausfinden, ob sich Ihre Aussage auf das von mir beschriebene Problem bezieht. :)
Vit Khudenko
9

Neben der Antwort von Emmanuels:

Beide Methoden startActivityund finishwerden nach dem Ende der aufrufenden Methode geplant, da beide vom UI-Thread verarbeitet werden.

scheffield
quelle
7

Ich würde die zweite Wahl treffen, ich unterstütze dies nicht auf irgendetwas, das ich aus offiziellen Quellen nachgeschlagen habe, aber es ist sinnvoller, die neue Aktivität zu starten, bevor Sie "Fertig stellen" aufrufen. Auf diese Weise wird die neue Aktivität über eine Absicht angezeigt und die jetzt Hintergrundaktivität kann alle Bereinigungsmethoden aufrufen.

Wenn Sie es umgekehrt machen, hat die Absicht möglicherweise keine Zeit zu feuern, bevor die Reinigung abgeschlossen ist. Dh wird die Aktivität startActivity () nach dem Aufruf von finish () aufrufen?

Ich hoffe, Sie verstehen, was ich zu sagen versuche, ich würde die zweite Option tun, nur um sicher zu gehen.

Blindware
quelle
Ja, ich habe deine Idee verstanden. Das klingt logisch. Aber ich kann mir nicht vorstellen, wann diese Situation möglich sein könnte
Tima
2

Ich hatte das ähnliche Problem:

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

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

hier, wenn ich benutze:

finish();
startActivity(A);

Es passiert etwas Verkabeltes: Aktivität B tritt in den Vordergrund anstelle von A! aber wenn ich den Code so ändere:

startActivity(A);
finish();

Alles scheint in Ordnung zu sein und Aktivität A wird sichtbar.

Ich weiß nicht , was das Problem ist, aber es scheint , dass im ersten Fall C vor der Ausführung des startActivity Befehls beendet ist , so dass die Rückseite Stapel Greifen die Situation und zeigt seine Top-Aktivität , die B! aber im zweiten Fall passiert alles normal.

Nargen
quelle
Wenn Sie die Anwendung beenden (), zieht Android die LRU-Aktivität vom Stapel, der B ist. Außerdem denke ich, dass finish () sofort und nicht asynchron ist.
Mehmet AVŞAR
0

Normalerweise mache ich das startActivity()vorher, finish()da ich denke, dass dies sicherstellen würde, dass der neue Bildschirm herauskommt, bevor der vorherige ausgeht.

Ich habe eine Anmeldeseite in meiner App. Nachdem sich der Benutzer erfolgreich angemeldet hat, ist die Anmeldeaktivität beendet und die Hauptaktivität ist aktiv. Es funktioniert gut in Android 4.

Heute wollte ich es in Material Design umschreiben. Ich habe jedoch ein großes Problem. Das neue Android-Studio erstellt leere Aktivitäten mit Materialdesign, das meiner Meinung nach viele Ressourcen beansprucht. Der gleiche Prozess, aber ich habe den Fehler bekommen

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

Es heißt, dass meine Apps beim mainActivityStart in meinem Telefonlogcat viele Ressourcen beanspruchen. Ich habe nichts in mainActivitynur, dass es das Standard-Material-Design-Layout ist.

Ich habe die Reihenfolge umgekehrt und jetzt funktioniert es ohne Fehler auf meinem Telefon.

hatted
quelle