L'activité arrive


1. La relation entre l'activité, la fenêtre et la vue

D'accord, je voulais au départ comprendre la relation entre eux, puis j'ai commencé à regarder leurs appels. processus... Au final, j'ai passé deux heures et n'en ai compris qu'une toute petite partie. Effectivement, ceux qui sont allés au fond pour apprendre le code source sont tous de grands maîtres, comme Lao Luo, qui n'y est pas encore parvenu. niveau. Ce qui suit consiste à vérifier les informations par vous-même. Après avoir lu le résumé du prochain morceau de code source, veuillez indiquer s'il y a quelque chose qui ne va pas ! Un diagramme récapitulatif est publié ci-dessous :

1.jpg

Analyse du processus : Après que Activity ait appelé startActivity, il appellera finalement le attach, puis implémentez une interface Ipolicy dans PolicyManager, puis implémentez un objet Policy, puis appelez la méthode makenewwindow(Context), qui renverra un objet PhoneWindow, et PhoneWindow C'est une sous-classe de Window. Dans ce PhoneWindow, il existe une classe interne de DecorView, qui est la vue racine de toutes les fenêtres d'application, c'est-à-dire le patron de View. Contrôlez directement si l'activité est affichée (en citant les mots originaux de l'ancien pilote...), d'accord, alors il y a un LinearLayout à l'intérieur, et il y a deux FrameLayouts à l'intérieur. Ils sont utilisés pour installer respectivement ActionBar et CustomView, et la mise en page chargée par. notre setContentView() est placé dans cette CustomView !

Résumez la relation entre les trois : Utilisons une métaphore tirée par les cheveux : On peut appeler respectivement ces trois catégories : peintres, toiles et objets dessinés au pinceau ; Le peintre dessine le motif avec le pinceau (LayoutInflater.infalte), puis le dessine sur la toile (addView) ! Enfin affiché (setContentView)


2. Quelques concepts d'activité, de tâche et de pile arrière

Comprenons ensuite le mécanisme de gestion de l'activité dans Android This It. implique deux noms : Task et Back Stack !

Analyse du concept :

Notre APP est généralement composée de plusieurs activités, et Android nous fournit une Tâche (tâche) Le concept de , C'est-à-dire collecter plusieurs activités liées, puis sauter et renvoyer les activités ! Bien entendu, cette tâche n'est qu'un Le concept de la couche frameworker et la structure de données qui implémente Task dans Android est Back Stack  ! Je pense que tout le monde connaît la structure des données de Stack en Java. La pile a les caractéristiques suivantes :

Premier entré, premier sorti (LIFO), les opérations couramment utilisées sont push et pop. Le haut est appelé le haut de la pile, et le bas est appelé. appelé la pile. Bottom

La Stack Stack dans Android présente également les caractéristiques ci-dessus. Voici comment elle gère l'activité :

Lors du passage à une nouvelle activité. , alors l'activité sera poussée sur la pile et deviendra le sommet de la pile ! Lorsque l'utilisateur clique sur le bouton Précédent, l'activité en haut de la pile apparaît et l'activité qui suit arrive en haut de la pile !

Jetons un coup d'œil à un organigramme donné dans le document officiel :

2.png

Analyse du processus :

Il existe trois activités A1, A2 et A3 dans l'application lorsque l'utilisateur clique sur l'application sur le lanceur. ou l'icône de l'écran d'accueil, Démarrez le principal A1, puis A1 démarre A2 et A2 démarre A3. À ce stade, il y a trois activités dans la pile, et ces trois activités sont dans. Dans la même tâche (Tâche), lorsque l'utilisateur appuie sur la touche retour, A3 apparaît et seuls A1 et A2 restent dans la pile. Si l'utilisateur appuie à nouveau sur la touche retour, Pop-up A2, et seul A1 reste dans la pile. Continuez à appuyer sur la touche retour, pop-up A1, la tâche est supprimée, c'est-à-dire que le programme se termine !

Puis j'ai vu deux autres photos dans le document officiel. Par curiosité, j'ai relu l'explication, puis j'en ai discuté avec les personnes du groupe :

3.png

Ensuite il y a cette explication :

4.png

Ensuite la conclusion est tirée :

La tâche est une activité La collection est un concept. La Back Stack est en fait utilisée pour stocker l'activité. Il peut y avoir plusieurs tâches, mais. Une seule pile est à l’avant à la fois, et les autres sont en arrière-plan ! Comment est née la pile ?

Réponse : lorsque nous cliquons sur l'icône pour ouvrir une nouvelle application via l'écran d'accueil, une nouvelle tâche sera créée ! Par exemple :
Nous ouvrons l'application en cliquant sur l'icône de l'application Carnet d'adresses. À ce moment, une nouvelle pile 1 sera créée, puis l'activité nouvellement générée sera ajoutée. Peut-être avons-nous ouvert la page SMS APP. dans l'application Carnet d'adresses, mais une nouvelle pile ne sera pas créée pour le moment, mais continuera à être ajoutée à la pile 1. Ceci est Android promeut une approche axée sur l'expérience utilisateur, c'est-à-dire que le basculement entre différentes applications peut donner aux utilisateurs l'impression qu'il s'agit de la même application. Une expérience utilisateur très cohérente, officiellement dite transparente ! ——————Si nous cliquons sur le bouton Accueil à ce moment pour revenir à l'écran d'accueil et que la pile 1 entre en arrière-plan, nous pouvons avoir les deux opérations suivantes :
1) Cliquez sur le bouton de menu (le bouton carré ), cliquez sur Ouvrir le programme tout de suite, puis la pile 1 revient au premier plan ! Ou on clique sur l'icône du carnet d'adresses sur l'écran d'accueil pour ouvrir l'APP. A ce moment, une nouvelle pile ne sera pas créée, et la pile 1 reviendra au premier plan !
2) Si nous cliquons sur une autre icône pour ouvrir une nouvelle APP à ce moment-là, alors une nouvelle pile 2 sera créée et la pile 2 passera au premier plan. Et la pile 1 continue de rester en arrière-plan ;
3) La même chose est vraie plus tard... et ainsi de suite !


3. Gestion des tâches

1) Traduction du document :

Bon, continuons avec le document, en commençant par la gestion des tâches dans le document, en gros Le la traduction est la suivante :


1) Traduction du document

Continuez à parcourir le document, en commençant par Gérer les tâches dans le document, la traduction est la suivante :

Comme mentionné ci-dessus, Android ajoutera l'activité nouvellement lancée avec succès à la même tâche et gérera plusieurs tâches selon le principe du « premier entré, premier sorti ». Avec Back Stack, les utilisateurs n'ont pas à se soucier de la façon dont les activités interagissent avec les tâches ou de la façon dont elles existent dans Back Stack ! Peut-être souhaitez-vous changer ce style de gestion normal. Par exemple, vous souhaitez qu'une de vos activités soit gérée dans une nouvelle Tâche ; Ou vous souhaitez uniquement instancier une certaine activité, ou vous souhaitez nettoyer toutes les activités de la tâche, à l'exception de l'activité racine, lorsque l'utilisateur quitte la tâche. Vous pouvez faire ces choses et bien plus encore en modifiant simplement AndroidManifest.xml <activity > peut être facilement implémenté en transmettant une intention spécialement identifiée à startActivity() dans le code. Gestion de l'activité. Les attributs que nous pouvons utiliser dans

<activity > sont les suivants :

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

Les principaux indicateurs d'intention que vous pouvez utiliser sont :

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP

D'accord, Ensuite, nous présenterons comment les utiliser une par une :


2) taskAffinity et allowTaskReparenting

Par défaut, toutes les activités d'une application ont une affinité , Cela les fait appartenir à la même tâche. Vous pouvez le comprendre comme un signe indiquant si elle fait partie de la même tâche. Cependant, chaque activité peut réussir. La propriété taskAffinity dans <activity> Les activités dans différentes applications peuvent partager la même affinité et différentes activités dans la même application Il peut également être défini sur une affinité différente. L'attribut Affinity fonctionne dans 2 situations :

1) Lorsque l'objet Intent qui démarre l'activité contient la balise FLAG_ACTIVITY_NEW_TASK : Lorsque l'objet Intent transmis à startActivity() contient la balise FLAG_ACTIVITY_NEW_TASK, le système recherchera une tâche différente de l'activité en cours pour l'activité qui doit être démarrée. Si l'attribut d'affinité de l'activité à démarrer est différent des attributs d'affinité de toutes les tâches en cours, le système créera une nouvelle tâche avec cet attribut d'affinité et poussera l'activité à démarrer dans la pile de tâches nouvellement créée, sinon l'activité ; sera poussé dans cet attribut Affinity dans la même pile.

2) L'attribut allowTaskReparenting est défini sur true Si la propriété AllowTaskReparenting d'une activité est vraie, elle peut alors être déplacée d'une tâche (Tâche1) vers une autre tâche (Tâche2) avec la même affinité (lorsque la Tâche2 est mise au premier plan). Si un fichier .apk contient plusieurs « applications » du point de vue de l'utilisateur, vous devrez peut-être attribuer différentes valeurs d'affinité à ces activités.


3) launchMode :

Quatre valeurs optionnelles, au cœur de nos recherches sur le mode de lancement, nous en parlerons en détail ci-dessous ! Ce sont : standard (par défaut), singleTop, singleTask, singleInstance


4) Effacer la pile

Lorsque l'utilisateur quitte la tâche pendant une longue période (la tâche en cours est transférée en arrière-plan), le système effacera toutes les activités de la tâche à l'exception de l'activité en bas de la pile. . De cette façon, lorsque l'utilisateur revient à la tâche, seule l'activité d'origine de cette tâche est conservée. Nous pouvons modifier les propriétés suivantes pour Changez ce comportement !

alwaysRetainTaskState : Si cette propriété de l'activité en bas de la pile est définie sur true, la situation ci-dessus ne se produira pas. Toutes les activités de la tâche seront enregistrées pendant une longue période.

clearTaskOnLaunchSi cet attribut de l'activité en bas de la pile est défini sur true, une fois que l'utilisateur quitte la tâche, Ensuite, les activités de la pile de tâches seront effacées jusqu'à ce qu'il ne reste que l'activité en bas de la pile. Cette situation coïncide avec Le contraire de AlwaysRetainTaskState. Même si l'utilisateur ne quitte que brièvement, la tâche reviendra à son état initial (Seule l'activité en bas de la pile reste).

finishOnTaskLaunch est similaire à clearTaskOnLaunch, mais il ne fonctionne que sur une seule activité opération, plutôt que la tâche entière. Il peut mettre fin à n'importe quelle activité, y compris l'activité en bas de la pile. Lorsqu'elle est définie sur true, l'activité en cours n'existe que dans le cadre de la tâche pendant la session en cours. Lorsque l'utilisateur quitte l'activité et revient, celle-ci n'existera pas.


4. Explication détaillée des quatre modes de chargement de l'activité :

Ensuite, expliquons les quatre modes de chargement en détail : Ce sont : standard (par défaut), singleTop, singleTask, singleInstance J'ai vu un article avec des images et des textes quand je passais du temps en ligne. L'explication du mode de démarrage est très bonne, elle peut être plus facile à comprendre ici :

Lien original : Explication graphique et textuelle détaillée du mode de démarrage de l'activité : standard, singleTop, singleTask et singleInstance

Texte original en anglais : Comprendre le mode de lancement d'Android Activity : standard, singleTop, singleTask et singleInstanceIl y a également une explication détaillée du mode de chargement : Explication détaillée des quatre modes de lancement et attributs taskAffinity d'Activity dans Android

Jetons d'abord un coup d'œil à l'image récapitulative :

5.png

Détails du mode :


mode standard :

Mode de démarrage standard, qui est également le mode d'activité de démarrage par défaut. Une activité démarrée dans ce mode peut être instanciée plusieurs fois, c'est-à-dire que plusieurs instances de l'activité peuvent exister dans la même tâche et chaque instance gérera un objet Intent. Si le mode de démarrage de l'activité A est standard et que A a déjà été démarré, redémarrer l'activité A dans A, c'est-à-dire appeler startActivity(new Intent(this, A.class)), redémarrera une instance de A au-dessus de A, c'est-à-dire que l'état actuel de la pile est A-->A.

6.jpg

7.jpg


mode singleTop :

Si une instance d'une activité démarrée en mode singleTop existe déjà dans le tâche le haut de la pile, Ensuite, lorsque cette activité sera redémarrée, une nouvelle instance ne sera pas créée, mais l'instance en haut de la pile sera réutilisée. Et la méthode onNewIntent() de l'instance sera appelée pour transmettre l'objet Intent à cette instance. Par exemple, si le mode de démarrage de A est singleTop et qu'une instance de A existe déjà en haut de la pile, Ensuite, lors de l'appel de startActivity(new Intent(this, A.class)) pour démarrer A, L'instance de A ne sera pas recréée, mais l'instance d'origine sera réutilisée et la méthode onNewIntent() de l'instance d'origine sera appelée. À l’heure actuelle, il existe encore une instance de A dans la pile de tâches. Si une instance d'une activité a démarré en mode singleTop S'il existe déjà dans la pile des tâches mais n'est pas en haut de la pile, son comportement est le même qu'en mode standard et plusieurs instances seront créées.

8.jpg


mode singleTask :

Une seule instance d'activité est autorisée dans le système. S'il existe déjà une instance dans le système, La tâche contenant cette instance sera déplacée vers le haut et l'intention sera envoyée via onNewIntent(). Sinon, une nouvelle activité sera créée et placée dans la tâche appropriée

9.jpg

Un problème mentionné dans la documentation officielle :

Le système créer une nouvelle tâche et instancier cette activité comme racine de la nouvelle tâche Cela nous oblige à définir taskAffinity Après avoir utilisé taskAffinity :

10.jpg

11.jpg



mode singleInstance

garantit que quelle que soit la tâche à partir de laquelle le système démarre l'activité, il ne créera qu'une seule instance d'activité et l'ajoutera en haut de la nouvelle pile de tâches. C'est-à-dire que les autres activités démarrées par cette instance s'exécuteront automatiquement dans une autre tâche. Lorsqu'une instance de l'activité est redémarrée, les tâches et instances existantes seront réutilisées. et cette instance s'appellera La méthode onNewIntent() transmet l'instance Intent à l'instance. Identique à singleTask, Il n’y aura qu’une seule instance d’activité de ce type dans le système à la fois.

12.jpg


5. Suppléments d'activité

Il se peut que certaines choses n'aient pas été mentionnées à propos de l'activité, je réserverai donc une place ici. J'ai raté, je serai là. Tout d'abord, c'est la suggestion de l'ami du groupe Zhuhai Kun de publier le cours de gestion d'activité de l'open source Chine. Eh bien, le voici, tout le monde peut l'utiliser directement. En projet~

1)开源中国客户端Activity管理类:

package net.oschina.app;

import java.util.Stack;

import android .app.Activity;
import android.app.ActivityManager;
import android.content.Context;


classe publique AppManager {

pile statique privée<Activité> ActivityStack;
instance AppManager privée statique ;

private AppManager(){}
/**
* Instance unique
*/
public static AppManager getAppManager(){
if(instance= =null){
instance=new AppManager();
}
return instance;
}
/**
* Ajouter une activité à la pile
*/
public void addActivity(Activity activity){
if(activityStack==null){
activityStack=new Stack<Activity>();
}
activityStack.add(activity);
}
/**
* Obtenez l'activité actuelle (la dernière poussée sur la pile)
*/
public Activity currentActivity(){
Activity activity=activityStack.lastElement();
return activity;
}
/**
* Terminer l'activité en cours (la dernière poussée sur la pile)
*/
public void finishActivity(){
Activity activity=activityStack.lastElement();
finishActivity(activity);
}
/**
* Terminer l'activité spécifiée
*/
public void finishActivity(Activity activity){
if(activity!=null){
activityStack.remove(activity);
activity.finish();
activity=null;
}
}
/* *
* Terminez l'activité avec le nom de classe spécifié
*/
public void finishActivity(Class<?> cls){
for (Activity activity : activityStack) {
if(activity.getClass().equals(cls) ){
finishActivity(activity);
}
}
}
/**
* Terminer toutes les activités
*/
public void finishAllActivity(){
for (int i = 0, size = activityStack.size(); je < taille; i++){
            if (null != activityStack.get(i)){
            activityStack.get(i).finish();
            }
    }
activityStack.clear();
}
/**
* Quitter l'application
*/
public void AppExit(Context context) {
try {
finishAllActivity();
ActivityManager activityMgr= (ActivityManager) context.getSystemService (Context.ACTIVITY_SERVICE);
ActivityMgr.restartPackage(context.getPackageName());
System.exit(0);
} catch (Exception e) { }
}
}

Résumé de cette section :

D'accord, c'est tout pour cette section. Les choses sont un peu amères et difficiles à comprendre. Sachons-le pour l'instant. Opérations associées :

  • Appuyez sur le bouton Accueil pour faire passer la tâche précédente en arrière-plan
  • Appuyez longuement sur le bouton Accueil pour afficher la liste des tâches récemment exécutées
  • Cliquez sur l'icône de l'application dans le lanceur ou l'écran d'accueil pour démarrer une nouvelle tâche, ou planifiez une tâche existante au premier plan
  • Lors du démarrage d'une activité en mode tâche unique, il recherchera dans le système si une activité appropriée est déjà disponible. La tâche existe, si elle existe, planifiera cette tâche au premier plan pour réutiliser cette tâche. S'il existe déjà une instance de l'activité à démarrer dans cette tâche, effacez toutes les activités au-dessus de cette instance et affichez cette instance à l'utilisateur. S'il n'y a aucune instance de l'activité à démarrer dans cette tâche existante, une instance est démarrée en haut de cette tâche. Si cette tâche n'existe pas, une nouvelle tâche sera démarrée et une instance de cette activité en mode SingleTask sera démarrée dans cette nouvelle tâche.
  • Lors du démarrage de l'activité de singleInstance, il recherchera dans le système s'il existe déjà une instance de cette activité. Si elle existe, la tâche où se trouve cette instance sera planifiée au premier plan et au premier plan. L'instance de cette activité sera réutilisée (il n'y a que cette activité), si elle n'existe pas, démarrera une nouvelle tâche et démarrera une instance de cette activité en mode singleInstance dans cette nouvelle tâche.

D'accord, c'est tout pour cette section. Les choses sur les modes de chargement des tâches et des activités sont encore assez compliquées, je vais publier les étapes de rédaction de cet article. Vous pouvez jeter un œil à certaines des références de l'époque~


Références :