Comprendre l'activité Android launchMode: standard, singleTop, singleTask et singleInstance

La traduction de l'article a été préparée spécialement pour les étudiants avancés en développement Android .




L'activité est l'un des concepts les plus frappants d'Android (le système d'exploitation mobile le plus populaire avec une architecture de gestion de la mémoire bien conçue qui implémente parfaitement le multitâche).

D'une manière ou d'une autre, avec le lancement d'Activity à l'écran, tout n'est pas si simple. La façon dont il a été exécuté est également importante. Il y a beaucoup de nuances dans ce sujet. L'un des plus importants est launchMode , dont nous parlerons dans cet article.

Chaque activité est créée pour travailler avec des objectifs différents. Certains d'entre eux sont conçus pour fonctionner séparément avec chaque intention, par exemple, l'activité envoyée pour composer le courrier électronique dans le client de messagerie. Alors que d'autres sont conçus pour fonctionner comme un singleton, comme une boîte aux lettres d'activité.

C'est pourquoi il est important d'indiquer si vous devez créer une nouvelle activité ou utiliser une activité existante, sinon cela peut entraîner de mauvaises UX ou des échecs. Grâce aux développeurs du noyau Android, cela est facile à faire avec launchMode , qui a été spécialement conçu pour cela.

Définition LaunchMode


Essentiellement, nous pouvons définir launchMode directement en tant qu'attribut de balise <activity>dans AndroidManifest.xml:

<activity
    android:name=".SingleTaskActivity"
    android:label="singleTask launchMode"
    android:launchMode="singleTask">

Il existe 4 types de launchMode disponibles. Regardons-les un par un.

standard

C'est le mode par défaut.

Le comportement d'une activité définie sur ce mode créera toujours une nouvelle activité qui fonctionnera séparément avec chaque intention envoyée. En fait, si 10 intentions ont été envoyées pour rédiger un e-mail, 10 activités doivent être lancées afin de servir chaque intention séparément. Par conséquent, un nombre illimité de ces activités peuvent être lancées sur l'appareil.

Comportement sur Android pré-Lollipop

Ce type d'activité sera créé et placé en haut de la pile dans la même tâche qui a envoyé l'intention.



L'image ci-dessous montre ce qui se passe lorsque nous partageons l'image avec l'activité standard. Il sera empilé dans la même tâche que celle décrite ci-dessus, bien qu'ils proviennent d'applications différentes.



Et c'est ce que vous verrez dans le gestionnaire de tâches. (Cela peut sembler un peu étrange)



Si nous basculons l'application vers une autre tâche, puis revenons à la galerie, nous verrons toujours que le launchMode standard est placé au-dessus de la tâche de la galerie. Par conséquent, si nous devons faire quelque chose dans la galerie, nous devons d'abord terminer notre travail dans cette activité supplémentaire.

Comportement sur Android Lollipop

Si ces activités concernent la même application, le comportement sera le même que dans l'implémentation pré-Lollipop - en plaçant sur la pile au-dessus de la tâche.



Mais dans le cas où l'intention est envoyée à partir d'une autre application, une nouvelle tâche sera créée et l'activité nouvellement créée sera placée comme racine, comme indiqué ci-dessous.



C'est ce que vous verrez dans le gestionnaire de tâches.



En effet, le système de gestion des tâches a été modifié dans Lollipop - il est devenu meilleur et plus compréhensible. Dans Lollipop, vous pouvez simplement revenir à la galerie, car il s'agit d'une tâche différente. Vous pouvez envoyer une autre intention, une nouvelle tâche sera créée qui servira l'intention de la même manière que la précédente.



Un exemple de ce type d'activité est l'activité de composition de courrier électronique ou l' activité de publication de statut du réseau social(mise à jour du statut sur les réseaux sociaux). Si vous avez une activité dans votre esprit qui traite chaque intention séparément, alors vous pensez à une activité standard .

singleTop


Le mode suivant est singleTop . Il se comporte de la même manière que la norme , ce qui signifie que vous pouvez créer autant d'instances d'activité SingleTop que nous le souhaitons. La seule différence est que s'il existe déjà une instance d'activité avec le même type en haut de la pile dans la tâche appelante, aucune nouvelle activité ne sera créée, à la place, l'intention sera envoyée à l'instance d'activité existante via la méthode onNewIntent().



En mode singleTop, vous devez considérer la gestion de l'intention entrante dans onCreate()et onNewIntent()pour qu'elle fonctionne dans tous les cas.

Un exemple d'utilisation de ce mode est la fonction de recherche. Pensons à créer un champ de recherche qui vous dirige vers SearchActivity pour voir les résultats de la recherche. Pour une meilleure UX, nous mettons généralement toujours le champ de recherche sur la page des résultats de recherche pour permettre à l'utilisateur d'effectuer la recherche suivante sans revenir en arrière.

Imaginez maintenant que si nous lançons toujours une nouvelle SearchActivity pour servir un nouveau résultat de recherche, nous obtiendrons 10 nouvelles activités pour 10 itérations de la recherche. Il serait très étrange de revenir en arrière, car vous devrez cliquer 10 fois en arrière pour parcourir tous les résultats de la recherche afin de revenir à l'activité racine.

Au lieu de cela, si SearchActivity est déjà en haut de la pile, il est préférable d'envoyer une intention à une instance d'activité existante et de la laisser mettre à jour le résultat de la recherche. Maintenant, il n'y aura qu'une seule SearchActivity située en haut de la pile, et vous pouvez simplement cliquer une fois sur le bouton de retour pour revenir à l'activité précédente. Cela a plus de sens.

Dans tous les cas, singleTop fonctionne dans la même tâche que l'appelant. Si vous vous attendez à ce que l'intention soit envoyée à une activité existante, placée au-dessus de toute autre tâche, je devrais vous décevoir en disant que là, cela ne fonctionne plus. Dans le cas où l'intention est envoyée d'une autre application à singleTop Activity, la nouvelle activité sera lancée sous le même aspect que pour standart launchMode (pré-Lollipop: placé au-dessus de la tâche appelante, Lollipop: une nouvelle tâche sera créée) .

singleTask


Ce mode est très différent de standart et singleTop. L'activité avec singleTask launchMode ne peut avoir qu'une seule instance dans le système (ala singleton) . Si une instance d'activité existe déjà dans le système, la tâche entière contenant l'instance sera déplacée vers le haut et l'intention sera fournie via la méthode onNewIntent(). Sinon, une nouvelle activité sera créée et placée dans la tâche correspondante.

Travailler dans une application

S'il n'y avait pas d'instance d'activité SingleTask dans le système, une nouvelle sera créée et elle sera simplement placée dans la pile dans la même tâche.



Mais si elle existe, toutes les activités situées au-dessus de cette activité à tâche unique seront automatiquement brutalement détruites correctement (le cycle de vie est terminé) afin d'afficher l'activité souhaitée en haut de la pile.Dans le même temps, Intent sera envoyé à singleTask Activity grâce à une merveilleuse méthode onNewIntent().



Cela n'a pas de sens du point de vue de l'expérience utilisateur, mais il est conçu de cette manière ...

Vous pouvez remarquer une nuance qui est mentionnée dans la documentation :

Le système crée une nouvelle tâche et instancie une instance d'activité à la racine de la nouvelle tâche.

Mais en pratique, il semble que cela ne fonctionne pas comme décrit . L'activité SingleTask est toujours placée en haut de la pile d'activité de la tâche, comme le montre le résultat de la commande dumpsys activity.

Ta

sk id #239
  TaskRecord{428efe30 #239 A=com.thecheesefactory.lab.launchmode U=0 sz=2}
  Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }
    Hist #1: ActivityRecord{429a88d0 u0 com.thecheesefactory.lab.launchmode/.SingleTaskActivity t239}
      Intent { cmp=com.thecheesefactory.lab.launchmode/.SingleTaskActivity }
      ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}
    Hist #0: ActivityRecord{425fec98 u0 com.thecheesefactory.lab.launchmode/.StandardActivity t239}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }
      ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}

Si vous voulez que l'activité singleTask se comporte comme décrit dans le document: créez une nouvelle tâche et mettez Activity comme activité racine. Vous devez définir un attribut taskAffinitypour l'activité singleTask comme suit.

<activity
    android:name=".SingleTaskActivity"
    android:label="singleTask launchMode"
    android:launchMode="singleTask"
    android:taskAffinity="">

Ce sera le résultat lorsque nous essaierons de courir SingleTaskActivity.





Votre tâche consiste à décider d'utiliser taskAffinityou non en fonction du comportement souhaité de l'activité.

Interaction avec une autre application

Dès que l'intention est envoyée à partir d'une autre application et qu'aucune instance de l'activité n'a été créée dans le système, une nouvelle tâche est créée avec une nouvelle activité placée comme activité racine.





S'il n'y a pas de tâche qui serait le propriétaire de l'activité singleTask appelante, une nouvelle activité sera affichée à la place.



Si une instance d'une activité existe dans une tâche, la tâche entière sera déplacée vers le haut et pour chaque activité individuelle située au-dessus d'une seule activité de tâche, le cycle de vie sera terminé. Si le bouton de retour est enfoncé, l'utilisateur doit passer par l'activité sur la pile avant de retourner à la tâche d'appel.



Un exemple d'utilisation de ce mode est une activité de point d'entrée, par exemple, la page Boîte de réception d'un client de messagerie ou une chronologie de réseau social. Ces activités ne supposent pas plus d'une instance, donc singleTask fera parfaitement son travail. Dans tous les cas, vous devez utiliser ce mode à bon escient, car dans ce mode, les activités peuvent être détruites sans confirmation de l'utilisateur, comme décrit ci-dessus.

seule instance


Ce mode est très similaire à singleTask, où une seule instance d'une activité peut exister sur un système. La différence est qu'une tâche qui a cette activité ne peut avoir qu'une seule activité - une qui a un attribut singleInstance . Si une autre activité est appelée à partir de ce type d'activité, une nouvelle tâche est automatiquement créée pour accueillir cette nouvelle activité. De même, si une activité singleInstance est appelée, une nouvelle tâche sera créée pour héberger cette activité.

En tout cas, le résultat est plutôt étrange. D'après les informations fourniesdumpsys, il est clair qu'il y a deux tâches dans le système, mais une seule apparaît dans le gestionnaire de tâches, selon celle qui est en haut. Par conséquent, bien qu'une tâche soit toujours en cours d'exécution en arrière-plan, nous ne pouvons pas la remettre au premier plan. Cela n'a aucun sens.

C'est ce qui se produit lorsqu'une seule activité d'instance est appelée alors qu'une activité existe déjà sur la pile.



Et voici ce que nous voyons dans le gestionnaire de tâches.



Comme cette tâche ne peut avoir qu'une seule activité, nous ne pouvons plus revenir à la tâche n ° 1. La seule façon de le faire est de redémarrer l'application à partir du lanceur, mais, par conséquent, la tâche singleInstance sera masquée en arrière-plan.

Quoi qu'il en soit, il existe des solutions de contournement à ce problème. Comme pour l'activité singleTask, affectez simplement un attribut taskAffinityà l'activité singleInstance, permettant à plusieurs tâches d'exister dans le gestionnaire de tâches.

<activity
    android:name=".SingleInstanceActivity"
    android:label="singleInstance launchMode"
    android:launchMode="singleInstance"
    android:taskAffinity="">

Maintenant, l'image a plus de sens.



Ce mode est rarement utilisé. Certains des cas d'utilisation pratiques sont un lanceur d'activité ou une application pour laquelle vous êtes sûr à 100% qu'il ne devrait y avoir qu'une seule activité. Dans tous les cas, je vous suggère de ne pas utiliser ce mode, sauf en cas d'urgence.

Drapeaux d'intention


En plus AndroidManifest.xmlde définir le mode de lancement directement sur , nous pouvons également ajuster le comportement à l'aide d'un outil appelé indicateurs d'intention , par exemple:

Intent intent = new Intent(StandardActivity.this, StandardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

sera lancé StandardActivityavec la condition singleTop launchMode.

Il existe plusieurs indicateurs avec lesquels vous pouvez travailler. Vous pouvez trouver plus d'informations à ce sujet ici .

J'espère que vous avez trouvé cet article utile =)

En savoir plus sur le cours

All Articles