Combien d'activités vs fragments?

185

Intro:

Le modèle de base "Tutoriel sur les fragments" ressemble à ceci:

  1. Sur une tablette, ayez une liste à gauche, des détails à droite.
  2. Les deux sont Fragmentset résident tous les deux dans le même Activity.
  3. Sur un téléphone, ayez une liste Fragmenten une Activity.
  4. Lancer un nouveau Activityavec les détails Fragment.

(par exemple, l' API des fragments Android 3.0 de Dianne Hackborn et le guide de l'API des fragments )

Sur les deux appareils, la fonctionnalité est dans le Fragments. (Facile)

Sur la tablette , l'application entière est 1Activity , sur le téléphone , il y en a beaucoupActivities .


Des questions:

  • Y a-t-il une raison de diviser l'application de téléphone en plusieurs Activities?

Un problème avec cette méthode est que vous dupliquez une grande partie de la logique dans la tablette principale Activityet dans le téléphone séparé Activities.

  • Ne serait-il pas plus facile de conserver le modèle 1 activité dans les deux cas, en utilisant la même logique de commutation Fragmentsd'entrée et de sortie (en utilisant simplement une disposition différente)?

De cette façon, la majeure partie de la logique réside dans Fragmentseux - mêmes, et il n'y a qu'une seule Activityduplication de code.

De plus, ce que j'ai lu sur le, ActionBarSherlockc'est qu'il semble fonctionner le mieux avec Fragmentsau lieu de Activities(mais je n'ai pas encore travaillé avec).

Les didacticiels sont-ils trop simplifiés ou ai-je manqué quelque chose de majeur dans cette approche?


Nous avons essayé les deux approches avec succès au bureau - mais je suis sur le point de démarrer un projet plus important et je veux rendre les choses aussi faciles que possible.

Quelques liens vers des questions connexes:


Mises à jour

A commencé la prime sur question - toujours pas convaincu de la raison pour laquelle je dois dupliquer la logique de mon application dans l'activité de ma tablette et dans chaque activité du téléphone.

J'ai également trouvé un article intéressant des gars de Square, qui vaut la peine d'être lu:

Richard Le Mesurier
la source
38
+1 pour une question géniale et bien écrite.
Siddharth Lele
c'est quelque chose qui me fait beaucoup souffrir ces jours-ci, actuellement je travaille sur une application dont le design comprend beaucoup de fragments et elle sera disponible à la fois sur téléphone et tablette, je cherche une voie médiane, mais je n'ai pas encore trouvé ...
Nixit Patel
1
Honnêtement, je ne veux pas offenser mais je pense que vous avez simplement accepté ce que vous vouliez entendre plutôt que la vraie réponse. La réponse de Scuba n'est pas recommandée par Google et le billet de blog que j'ai aimé explique pourquoi.
pjco du
1
@pjco Plus précisément, je ne suis pas d'accord avec l'idée d'avoir une onItemSelected()méthode dans l'activité. Dans ma "vraie" application, j'ai de nombreuses listes et sous-listes. Ce modèle suggère que mon activité Tab doit avoir une onItemSelected()méthode pour gérer chacune des listes. De plus, les activités téléphoniques doivent chacune avoir la même logique dupliquée à l'intérieur de chacune d'elles. À mon humble avis, il est bien préférable de mettre la logique de l'élément sélectionné dans chaque fragment - il n'y a pas de duplication et je préfère cette façon de structurer le code. J'espère que cela aide
Richard Le Mesurier
2
Je suis actuellement accroché à ce dilemme au travail. Les fragments se chargent beaucoup plus rapidement que le lancement de nouvelles activités, j'ai donc commencé à implémenter une architecture d'activité unique. J'ai cependant rencontré un problème, c'est-à-dire que je n'arrive pas à trouver un bon moyen de prendre en charge les configurations multi-fragments sans faire quelque chose de piraté. Voir cette question .
theblang

Réponses:

41

Je conviens que les tutoriels sont très simplifiés. Ils introduisent simplement Fragmentsmais je ne suis pas d'accord avec le modèle suggéré.

Je conviens également que ce n'est pas une bonne idée de dupliquer la logique de votre application dans de nombreuses activités (voir le principe DRY sur wikipedia ).


Je préfère le modèle utilisé par l' ActionBarSherlockapplication Fragments Demo ( téléchargez ici et code source ici ). La démo qui correspond le plus au didacticiel mentionné dans la question est celle appelée "Mise en page" dans l'application; ou FragmentLayoutSupportdans le code source.

Dans cette démo, la logique a été déplacée du Activityet vers le Fragment. Le TitlesFragmentcontient en fait la logique de modification des fragments. De cette façon, chaque activité est très simple. La duplication de nombreuses activités très simples, où aucune logique n'est à l'intérieur des activités, le rend très simple.

En mettant la logique dans les fragments, il n'est pas nécessaire d'écrire le code plus d'une fois ; il est disponible quelle que soit l'activité dans laquelle le fragment est placé. Cela en fait un modèle plus puissant que celui suggéré par le didacticiel de base.

    /**
    * Helper function to show the details of a selected item, either by
    * displaying a fragment in-place in the current UI, or starting a
    * whole new activity in which it is displayed.
    */
    void showDetails(int index)
    {
        mCurCheckPosition = index;

        if (mDualPane)
        {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            getListView().setItemChecked(index, true);

            // Check what fragment is currently shown, replace if needed.
            DetailsFragment details = (DetailsFragment) getFragmentManager()
                .findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index)
            {
                // Make new fragment to show this selection.
                details = DetailsFragment.newInstance(index);

                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager()
                    .beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        }
        else
        {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            Intent intent = new Intent();
            intent.setClass(getActivity(), DetailsActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);
        }
    }

Un autre avantage du modèle ABS est que vous ne vous retrouvez pas avec une activité de tablette contenant beaucoup de logique, ce qui signifie que vous économisez de la mémoire. Le modèle du didacticiel peut conduire à une très grande activité principale dans une application plus complexe; car il doit gérer la logique de tous les fragments qui y sont placés à tout moment.

Dans l'ensemble, ne le considérez pas comme obligé d'utiliser de nombreuses activités. Considérez-le comme la possibilité de diviser votre code en plusieurs fragments et d'économiser de la mémoire lors de leur utilisation.

Stephen Asherson
la source
merci pour une réponse complète - j'ai regardé les démos ABS, et je pense qu'il y a beaucoup de bon code là-bas. Je vais essayer de déplacer une grande partie de ma logique dans les fragments à la place
Richard Le Mesurier
L'application de démonstration a déménagé ici: play.google.com/store/apps/…
Philipp E.
Je pense que le modèle que vous décrivez provient de l'exemple de code original de Google: android-developers.blogspot.com/2011/02/ ... Je pense qu'ActionBarSherlock vient de porter le code de démonstration Google pour utiliser les classes ABS.
Dan J
17

Je pense que vous êtes sur la bonne voie. (Et oui, les tutoriels sont trop simplifiés).

Dans une mise en page de tablette, vous pouvez utiliser une seule activité et échanger des fragments d'entrée et de sortie (dans plusieurs «volets»). Dans une disposition de téléphone, vous pouvez utiliser une nouvelle activité pour chaque fragment.

Ainsi:

entrez la description de l'image ici

Cela peut sembler beaucoup de travail supplémentaire, mais en utilisant plusieurs activités pour les téléphones, vous activez le cycle de vie de base de l'activité et la réussite de l'intention. Cela permet également au framework de gérer toutes les animations et la back-stack.

Pour aider à réduire le code, vous pouvez utiliser a BaseActivityet étendre à partir de cela.

Donc, si l'utilisateur a une tablette que vous utiliseriez MyMultiPaneFragActivityou quelque chose de similaire. Cette activité est responsable de la gestion des rappels des fragments et des intentions de routage vers le fragment correct (comme une intention de recherche)

Si l'utilisateur a un téléphone, vous pouvez utiliser une activité standard avec très peu de code et l'étendre MyBaseSingleFragActivityou quelque chose de similaire. Ces activités pourraient être très simples, 5 à 10 lignes de code (peut-être même moins).

La partie délicate est les intentions de routage et ainsi de suite. * (Modifier: voir plus ci-dessous).

Je pense que la raison pour laquelle c'est la méthode recommandée est d'économiser de la mémoire et de réduire la complexité et le couplage. Si vous échangez des fragments, le FragmentManagerconserve une référence à ce fragment pour la pile arrière. Cela simplifie également ce qui devrait être «en cours» pour l'utilisateur. Cette configuration dissocie également les vues, la disposition et la logique du fragment du cycle de vie de l'activité. De cette façon, un fragment peut exister dans une seule activité, aux côtés d'un autre fragment (deux volets), ou dans une activité à trois volets, etc.

* L'un des avantages d'un routage d'intention régulier est que vous pouvez lancer une activité explicitement à partir de n'importe où dans la pile arrière. Un exemple pourrait être le cas des résultats de recherche. (MySearchResults.class).

Lisez ici pour en savoir plus:

http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html

Cela peut être un peu plus de travail initial, car chaque fragment doit bien fonctionner dans des activités distinctes, mais cela porte généralement ses fruits. Cela signifie que vous pouvez utiliser des fichiers de mise en page alternatifs qui définissent différentes combinaisons de fragments, garder le code de fragment modulaire, simplifier la gestion de la barre d'action et laisser le système gérer tout le travail de la pile arrière.

pjco
la source
Concernant l'avantage MySearchResults - vous suggérez d'avoir une manière différente de répondre à cette intention en fonction du combiné ou de la tablette - pourquoi est-ce mieux que d'avoir une seule activité qui répond dans les deux cas? Vous suggérez, sur la tablette, il n'y a pas de routage d'intention régulier - vous devez donc résoudre le problème de la tablette de toute façon. Pourquoi ne pas utiliser cette solution sur le combiné aussi?
Richard Le Mesurier
L'avantage ici est que le code de votre tablette peut s'attendre à être acheminé vers plusieurs volets. Parfois, vous souhaiterez changer plusieurs volets sur une seule intention. Comme les résultats de la recherche sur la gauche avec les détails du premier élément dans le volet plus grand vers la droite. Ce code ne serait pas portable dans une seule mise en page.
pjco le
Pourquoi est-il correct de changer de fragment quand il y en a beaucoup, mais si un seul fragment est visible, je ne dois pas passer à un autre fragment?
Richard Le Mesurier
Je ne suis pas sûr de comprendre ce que vous voulez dire, mais pour clarifier mon commentaire ci-dessus: Parfois, vous voudrez peut-être changer plus d'un fragment en même temps dans une mise en page multi-fragment. Cela nécessite du code pour changer 2 fragments, que vous ne réutiliseriez pas dans une seule mise en page de fragment
pjco
Vous êtes le bienvenu :) Veuillez voter pour ou accepter si vous pensez que la réponse est utile
pjco
6

Voici la réponse de Reto Meier à ce sujet, tirée de cette vidéo du cours Android Fundamentals d' Udacity .

Il y a un certain nombre de raisons pour lesquelles vous feriez mieux de diviser votre application en différentes activités.

  • Avoir une seule activité monolithique augmente la complexité de votre code, ce qui le rend difficile à lire, à tester et à maintenir.
  • Rend la création et la gestion des filtres d'intention beaucoup plus difficiles.
  • Augmente le risque de coupler étroitement des composants indépendants.
  • Rend beaucoup plus susceptible d'introduire des risques de sécurité si l'activité unique comprend à la fois des informations sensibles et des informations pouvant être partagées en toute sécurité.

Une bonne règle d'or consiste à créer une nouvelle activité chaque fois que le contexte change. Par exemple, afficher un autre type de données et passer de la visualisation à la saisie de données.

Aditya Naique
la source
Fait intéressant, le titre de la vidéo est "Pourquoi nous n'utilisons pas que des fragments"
Richard Le Mesurier
c'est une bonne approche, je suis confronté à des tonnes de problèmes avec une seule activité et plusieurs fragments ... exp probablement réelle
GvSharma
4

Un problème avec cette méthode est que vous dupliquez une grande partie de la logique dans l'activité principale de la tablette et dans les activités téléphoniques séparées.

Dans le modèle maître-détails, il y a deux activités. On montre les deux fragments sur des écrans plus grands et seulement le fragment "maître" sur des écrans plus petits. L'autre montre le fragment «détail» sur des écrans plus petits.

Votre logique de détail doit être liée au fragment de détail. Par conséquent, il n'y a pas de duplication de code liée à la logique de détail entre les activités - l'activité de détail affiche simplement le fragment de détail, peut-être en passant les données d'un Intentextra.

De plus, ce que j'ai lu à propos de l'ActionBarSherlock, c'est qu'il semble fonctionner mieux avec des fragments plutôt qu'avec des activités (mais je n'ai pas encore travaillé avec).

ActionBarSherlock n'a pas plus à voir avec les fragments que la barre d'action native, puisque ActionBarSherlock est purement un backport de la barre d'action native.

CommonsWare
la source
Que pensez-vous de l'idée d'une seule activité?
theblang
@mattblang: Tant que vous avez la bonne navigation, cela ne pose aucun problème.
CommonsWare
1
J'ai essayé de refactoriser une architecture à activité unique car le remplacement d'un fragment est tellement plus rapide que le lancement d'une nouvelle activité avec le même fragment. J'ai l'impression de rencontrer trop de problèmes, comme ça . La plupart des exemples que je trouve en ligne, en particulier pour les configurations multi-fragments comme le maître-détail, n'utilisent pas une seule activité. Je suis donc un peu confronté à un dilemme.
theblang
0

En référence à la première question de "Y a-t-il une raison de diviser l'application pour téléphone en plusieurs activités?" - Oui. cela se résume simplement à l'espace disponible, une tablette donne plus de place aux développeurs, permettant ainsi aux développeurs d'en mettre plus sur un seul écran. Android nous dit que les activités peuvent fournir un écran . Donc, ce que vous pouvez faire avec 1 grand écran sur une tablette, c'est quelque chose qui peut devoir être réparti sur plusieurs écrans sur un téléphone, car il n'y a pas assez de place pour tous les fragments.

EFlisio
la source
1ère phrase - "Une activité est un composant d'application qui fournit un écran avec lequel les utilisateurs peuvent interagir pour faire quelque chose,". Je vois une erreur dans ma déclaration originale, je ne voulais pas mettre "sont un autre écran",
EFlisio