Android 4.4.X: TaskAffinity & LaunchMode vs. Aktivitätslebenszyklus

8

Ich habe eine einfache Anwendung entwickelt, die seltsames Verhalten auf Android 4.4.X-Geräten demonstriert, die ich bemerkt habe.

Sagen wir, ich möchte 2 "Haupt" -Aktivitäten haben, wobei die erste "Hello" (durch Starten von 'HelloActivity') jedes zweite Mal, wenn sie wieder aufgenommen wird und die zweite android:launchMode="singleTask" android:taskAffinity=".MyAffinity" definiert hat. Der zweite wird von dem ersten gestartet.

Mein Code

Manifestieren ist ziemlich einfach:

%Vor%

MainActivity startet AffinityTestActivity beim Klicken auf die Schaltfläche und protokolliert dessen Lebenszyklus. Es startet auch HelloActivity jedes zweite Mal, wenn es fortgesetzt wird:

%Vor%

AffinityTestActivity ruft finish () beim Klicken auf die Schaltfläche auf und protokolliert dessen Lebenszyklus:

%Vor%

HelloActivity ist genau wie AffinityTestActivity in der Tat - es hat nur eine Schaltfläche zum Aufrufen von finish () und printlns zum Protokollieren seines Lebenszyklus.

Testszenario

  1. Starten Sie MainActivity.
  2. Starten Sie AffinityTestActivity.
  3. Beenden Sie AffinityTestActivity (wenn AffinityTestActivity abgeschlossen ist, wird MainActivity wieder aufgenommen und HelloActivity wird gestartet).
  4. Ausgabe analysieren.

Logs

Android 4.4.2 und 4.4.3 : (getestet auf Nexus 7 II und Samsung Galaxy S5) Wie Sie sehen können, endet das Protokoll mit HelloActivity onPause, was keinen Sinn macht (HelloActivity wird oben in Schritt 3 angezeigt). Auch AffinityTestActivity wird nicht zerstört und MainActivity wird nicht pausiert.

%Vor%

Ältere Android-Versionen (& lt; 4.4.2, getestet auf 2.3.5., 4.1.2 und 4.2.1 Geräten, 4.0.3 Emulator) funktionieren wie erwartet - HelloActivity wird danach nicht angehalten onResume und AffinityTestActivity wird zerstört:

%Vor%

Meine Frage (n)

  • Warum wird meine HelloActivity auf Android 4.4.X-Geräten gleich nach dem Start pausiert und oben angezeigt?
  • Wie kann ich das vermeiden und die Anwendung zwingen, einen "normalen" Aktivitätslebenszyklus zu haben, wie es ältere Android-Versionen (& lt; 4.4.2) tun?

Ich entwickle Anwendungen, die viel komplexer sind und mit dem Lebenszyklus ihrer Aktivitäten funktionieren. Dieses Verhalten verletzt die Funktionalität meiner Anwendung.

Vielen Dank!

    
Berťák 20.06.2014, 10:24
quelle

1 Antwort

4

Ich habe ein Projekt erstellt, das auf dem von Ihnen bereitgestellten Code basiert, und ich konnte Ihr Problem auf meinem eigenen Nexus 7 reproduzieren. Obwohl ich keine konkrete, akademische Antwort für Sie habe, ist meine beste Erklärung die folgende :

1) MainActivity wird gestartet

2) Schaltfläche geklickt. AffinityTestActivity wird in einer neuen Aufgabe gestartet.

3) Schaltfläche geklickt. AffinityTestActivity beendet.

4) MainActivity wird innerhalb der alten Aufgabe fortgesetzt.

5) In MainActivity onResume wird die Absicht für HelloActivity innerhalb der gleichen Aufgabe aufgerufen.

6) Der mysteriöse Teil, der nach ein bisschen Basteln meine Theorie ist: Ein Teil der alten Aufgabe in den Vordergrund zu stellen, interagiert weiterhin mit MainActivity, der Wurzel der alten Aufgabe, während des onResume-Aufrufs. Diese Interaktion bewirkt, dass die onPause-Methode von HelloActivity ausgelöst wird (wahrscheinlich nicht von den Betriebssystementwicklern beabsichtigt). Dies ist zwar nicht die befriedigendste Antwort (angesichts meiner begrenzten Erfahrung mit Plancode und Timing-Problemen auf Betriebssystemebene), aber meine Experimente weisen auf etwas in dieser Richtung hin. Mein erster Hinweis auf diese Störung war dieser häufige Fehler in logcat:

%Vor%

Wie Sie sehen können, wurde die onPause-Methode von MainActivity erst aufgerufen, nachdem HelloActivity beendet wurde. Das ist auch nicht richtig. Das zeigt mir, dass das Starten einer Aktivität in onResume, während die Aufgabe in den Vordergrund gebracht wird, einige unbeabsichtigte Konflikte im Lebenszyklus verursacht.

Um zu sehen, was passiert ist, wenn ich der Aktivität / Aufgabe eine Sekunde gegeben habe, um eine ungesehene Verarbeitung abzuschließen, habe ich einen Handler verwendet, um die HelloActivity-Absicht in MainActivity aufzurufen:

%Vor%

Dies führte zu einem viel besseren Verhalten. HelloActivity hat sich wie gewünscht verhalten und onPause wurde nicht aufgerufen. Offensichtlich ist dies nicht ideal für den Arbeitscode, aber es zeigt, dass das einfache Verschieben der Ausführungszeit um eine Sekunde das Problem behebt. Weitere Hinweise auf interne Planungskonflikte innerhalb der Aufgabe.

Als nächstes habe ich versucht, HelloActivity eine eigene Aufgabe zu geben:

%Vor%

(Für die Aufzeichnung ist diese Konfiguration nicht sehr sinnvoll, aber ich nehme an, dass sie ein Szenario in Ihrem realen Projekt widerspiegelt, das einen logischeren Zweck hat.)

In diesem Szenario funktioniert alles gut. Der Lebenszyklus von HelloActivity beeinträchtigt nicht den Lebenszyklus von MainActivity. Allerdings hat es jetzt den Overhead seiner eigenen Aufgabe und die damit verbundenen Probleme, eine Aktivität als singleTask auszuführen (durch Drücken der "Home" -Schaltfläche und erneutes Öffnen der App gelangen Sie zu MainActivity, wodurch HelloActivity in seiner neuen Aufgabe nicht verfügbar ist, obwohl es dort ist war die letzte Aktivität, die vor dem Schließen der App angezeigt wurde).

Meine beste Empfehlung wäre, einen Weg zu finden, dieses spezielle Szenario zu vermeiden. :) Es scheint, als wäre es ein Bug in späteren Versionen von Android, wenn auch ein seltsamer Randfall. Wenn das keine Option ist, könnten Sie einer der Routen folgen, die ich benutzt habe, um es zu umgehen. Ich habe ein paar andere Dinge ausprobiert, aber es ist schwierig, die Tatsache zu umgehen, dass die Planung auf einer OS-Ebene außerhalb unserer Reichweite gesteuert wird.

Tut mir leid, dass ich Ihnen keine tiefere Antwort geben konnte, aber das ist alles, was ich für jetzt habe!

    
Brian 24.06.2014, 15:33
quelle