J'ai lu dans la documentation Android Android en définissant la propriété launchMode de mon activité sur singleTop OR en ajoutant l'indicateur FLAG_ACTIVITY_SINGLE_TOP
À mon intention, cet appel startActivity(intent)
réutiliserait une seule instance d'activité et me donnerait l'intention dans le rappel onNewIntent
. J'ai fait ces deux choses, et onNewIntent
ne se déclenche jamais et onCreate
se déclenche à chaque fois. Les documents indiquent également que this.getIntent()
renvoie l'intention qui a été transmise pour la première fois à l'activité lors de sa création. Dans onCreate
j'appelle getIntent
et j'en reçois un nouveau à chaque fois (je crée l'objet d'intention dans une autre activité et j'y ajoute un extra ... cet extra devrait être le même à chaque fois s'il me renvoyait le même objet d'intention). cela m'amène à croire que mon activité n'agit pas comme un "single top", et je ne comprends pas pourquoi.
Pour ajouter un peu de fond au cas où il me manque simplement une étape requise, voici ma déclaration d'activité dans le manifeste et le code que j'utilise pour lancer l'activité. L'Activité elle-même ne fait rien de valable à ce sujet:
dans AndroidManifest.xml:
<activity
Android:name=".ArtistActivity"
Android:label="Artist"
Android:launchMode="singleTop">
</activity>
dans mon activité d'appel:
Intent i = new Intent();
i.putExtra(EXTRA_KEY_ARTIST, id);
i.setClass(this, ArtistActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
Avez-vous vérifié si onDestroy()
était également appelé? C'est probablement la raison pour laquelle onCreate()
est invoquée à chaque fois au lieu de onNewIntent()
, qui ne serait appelée que si l'activité existe déjà.
Par exemple, si vous quittez votre activité via le bouton BACK, elle est détruite par défaut. Mais si vous montez plus haut sur la pile d'activités dans d'autres activités et à partir de là, appelez à nouveau votre ArtistActivity.class
, Il sautera onCreate()
et ira directement à onNewIntent()
, car l'activité a déjà été créé et puisque vous l'avez défini comme singleTop
Android n'en créera pas une nouvelle instance, mais prenez celle qui traîne déjà.
Ce que je fais pour voir ce qui se passe, j'implémente des fonctions factices pour tous les différents états de chaque activité, donc je sais toujours ce qui se passe:
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
}
Idem pour onRestart()
, onStart()
, onResume()
, onPause()
, onDestroy()
Si ce qui précède (bouton BACK) n'était pas votre problème, implémenter ces mannequins vous aidera au moins à le déboguer un peu mieux.
La réponse acceptée n'est pas tout à fait correcte. Si onDestroy () était appelé précédemment, alors oui, onCreate () serait toujours appelé. Cependant, cette déclaration est fausse : "Si vous montez plus haut sur la pile d'activités dans d'autres activités et à partir de là, appelez à nouveau votre ArtistActivity.class, il sautera onCreate () et accédez directement à onNewIntent () "
La section "singleTop" de http://developer.Android.com/guide/components/tasks-and-back-stack.html explique clairement comment cela fonctionne (attention au texte en gras ci-dessous; je ' ve également prouvé par mon propre débogage):
"Par exemple, supposons que la pile arrière d'une tâche se compose de l'activité racine A avec les activités B, C et D en haut ( la pile est ABCD; D est en haut ). Une intention arrive pour une activité de type D. Si D a le mode de lancement "standard" par défaut, une nouvelle instance de la classe est lancée et la pile devient ABCDD. Cependant, si le mode de lancement de D est "singleTop", l'instance existante de D reçoit l'intention via onNewIntent (), car elle se trouve en haut de la pile - la pile reste ABCD. Cependant, si une intention arrive pour une activité de type B, alors une nouvelle instance de B est ajoutée à la pile, même si son mode de lancement est "singleTop". "
En d'autres termes, le démarrage d'une activité via SINGLE_TOP ne réutilisera l'activité existante que si elle est déjà en haut de la pile. Cela ne fonctionnera pas si une autre activité dans cette même tâche est en haut (par exemple, l'activité qui exécute startActivity (SINGLE_TOP)); une nouvelle instance sera créée à la place.
Voici deux façons de résoudre ce problème afin d'obtenir le comportement SINGLE_TOP que vous souhaitez - dont le but général est de réutiliser une activité existante, à la place d'en créer un nouveau ...
Première manière (comme décrit dans la section commentaire de la réponse acceptée): Vous pouvez ajouter un launchMode de "singleTask" à votre activité. Cela forcerait onNewIntent () car singleTask signifie qu'il ne peut y avoir qu'une seule instance d'une activité particulière dans une tâche donnée. C'est une solution quelque peu hacky car si votre application a besoin de plusieurs instances de cette activité dans une situation particulière (comme je le fais pour mon projet), vous êtes foutu.
Deuxième façon (meilleure): Au lieu de FLAG_ACTIVITY_SINGLE_TOP, utilisez FLAG_ACTIVITY_REORDER_TO_FRONT. Cela réutilisera l'instance d'activité existante en la déplaçant vers le haut de la pile (onNewIntent () sera appelé comme prévu).
Le but principal de FLAG_ACTIVITY_SINGLE_TOP est d'empêcher la création de plusieurs instances d'une activité. Par exemple, lorsque cette activité peut être lancée via une intention qui vient de l'extérieur de la tâche principale de votre application. Pour la commutation interne entre les activités de mon application, j'ai trouvé que FLAG_ACTIVITY_REORDER_TO_FRONT est généralement ce que je veux à la place.
Réglez ce drapeau à votre intention:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)