Les fondamentaux de Android Fragments: pourquoi? Est-ce que c'est conceptuellement faux?

J'ai une question sur la «programmation correcte» dans Android.

Je développe actuellement une application utilisant des fragments. Il implique des fragments ajoutés dynamiquement à Activité, des fragments gonflés à partir de XML, des fragments imbriqués à partir de XML ou ajoutés dynamiquement. Disons simplement un peu de tout.

Le concept sur lequel se concentre cette question est le processus de communication impliqué dans les fragments. Alors, j'ai lu les documents et ce n'est pas la première fois que j'essaie d'utiliser des fragments.

Le bon sens (et les docs) indiquent que si un Fragment veut parler ou communiquer avec son activité, nous devrions utiliser une interface.

Exemple:

TestFragment

public class TestFragment extends Fragment { private TestFragmentInterface listener; public interface TestFragmentInterface { void actionMethod(); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { if (getActivity() instanceof TestFragmentInterface) { listener = (TestFragmentInterface) getActivity(); } // sending the event if (listener != null) listener.actionMethod(); } } 

TestActivity

 public class Test implements TestFragmentInterface { @Override public void actionMethod() { .. } } 

Tout va bien ici.

Cela améliore la réutilisation, car mon TestFragment de cette façon peut interagir avec tout type d'activité, étant donné que l'activité implémente l'interface que je déclare.

Dans l'autre sens, l'activité peut interagir avec le fragment en tenant une référence et en appelant ses méthodes publiques. C'est aussi le moyen suggéré de communication fragment-à-fragment, en utilisant l'activité comme un pont.

C'est cool, mais parfois, il est préférable d'utiliser une interface pour que ce soit trop "trop".

Question A

Dans le scénario, les fragments que je attache ont un rôle assez ciblé, ce qui signifie qu'ils sont terminés pour cette activité particulière et ne seraient pas utilisés autrement, est-ce qu'il est conceptuellement faux d'ignorer l'implémentation de l'interface et de faire quelque chose comme

 ((TestActivity) getActivity().myCustomMethod(); 

?

Cela va aussi au scénario où (pas mon cas, mais en prenant simplement comme "dans son pire") mon activité doit faire face à une grande variété de ces fragments DIFFERENTS, ce qui signifie qu'il devrait implémenter une méthode pour chaque fragment qu'il devrait gérer . Cela amène le code à un gros désordre de "lignes potentiellement non nécessaires".

En avançant: toujours avec l'utilisation de fragments «ciblés», visait à travailler uniquement d'une certaine façon, qu'est-ce que l'utilisation de fragments imbriqués?

Les a ajouté comme

 public class TestFragment extends Fragment { private void myTestMethod() { NestedFragment nested = new NestedFragment(); getChildFragmentManager() .beginTransaction() .add(R.id.container, nested) .commit(); } } 

Cela lie NestedFragment à TestFragment. Je le répète encore, NestedFragment, tout comme TestFragment, ne doit être utilisé que de cette façon, il ne sert à rien de travailler autrement.

Retour à la question, comment dois-je me comporter dans cette situation?

Question B

1) dois-je fournir une interface dans NestedFragment, et faire pour que TestFragments implémente NestedFragmentInterface? Dans ce cas, je serais le suivant

NestedFragment

 public class NestedFragment extends Fragment { private NestedFragmentInterface listener; public interface NestedFragmentInterface { void actionMethodNested(); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { if (getParentFragment() instanceof NestedFragmentInterface) { listener = (NestedFragmentInterface) getParentFragment(); } // sending the event if (listener != null) listener.actionMethodNested(); } } 

2) devrait (ou pourrait) ignorer l'interface, puis appeler

 getParentFragment().publicParentMethod(); 

?

3) devrais-je créer l'interface dans NestedFragment, mais laissez-la l'implémenter, afin que l' activité appelle TestFragment?

Question C

En ce qui concerne l'idée d'utiliser l'Activité comme un pont entre les fragments, je crois qu'il est fait pour un cycle de vie approprié de la gestion de tous ces objets. Est-il encore viable de faire un fragment-fragment direct (utilisant une interface ou appeler directement des méthodes publiques) en essayant de gérer manuellement l'exception que le système pourrait me jeter?

2 Solutions collect form web for “Les fondamentaux de Android Fragments: pourquoi? Est-ce que c'est conceptuellement faux?”

Je vais essayer de tout dégager un peu.

Tout d'abord, considérez que vous approchez de définir l'auditeur pour le fragment. Il est inutile de définir l'auditeur dans la méthode onViewCreated, car il se lie à un auditeur de rechute excédentaire, tout fragment est créé. Il suffit de le configurer dans la méthode onAttach.

J'ai parlé des lignes de code. Permettez-moi de remarquer, il est bon que BaseFragment ait mis en œuvre un comportement commun dans votre application en définissant FragmentListener en créant une vue à partir d'une ressource.

Et plus que cela pour réduire les lignes de code et pour obtenir une partie de la réutilisation du code, vous pouvez utiliser le générique dans BaseFragment. Alors regardez l'extrait de code suivant:

 public abstract BaseFragment<T extends BaseFragmentListener> extends Fragment { T mListener; public void onAttach(Activity activity) { super.onAttach(activity); if (Activity instanceof T) mListener = (T) activity; } abstract int getLayoutResourceId(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(getLayoutResourceId(), null); // you can use some view injected tools here, mb ButterKnife return layout; } } 

Réponse A (pour la question A):

Si vous avez un fragment exclusivement une activité, vous devez décider: "Avez-vous vraiment besoin d'utiliser Fragment ici?". Mais mb, il est bon d'avoir un fragment exactement pour une activité afin d'extraire une logique de vue de l'activité et de supprimer la logique de base. Mais pour effacer la logique d'architecture de base pour votre application, utilisez les auditeurs. Cela facilitera la vie pour les autres développeurs

Réponse B: Pour les fragments imbriqués, vous devez résoudre, ce qu'ils doivent utiliser l'activité exacte ou simplement des fragments et l'utiliser comme un pont vers un autre système. Si vous savez que le fragment imbriqué sera imbriqué à tout moment, vous devez déclarer le fragment parent comme un auditeur, sinon vous devez utiliser une autre approche.

Remarque: comme approche de base pour communiquer entre une partie différente de l'application, vous pouvez utiliser les événements, essayez également d'examiner le bus d'événements par exemple. Il vous donne une approche commune pour la communication et vous pouvez extraire la logique d'appeler des méthodes personnalisées d'auditeurs et plus une autre, toute logique sera située dans la gestion des événements et vous aurez un système de médiateur pour la coopération.

Réponse C: J'explique en partie une des approches de la coopération entre fragments. L'utilisation d'un répartiteur d'événements vous évite d'avoir de nombreux auditeurs pour toutes les communications différentes. Certaines fois, c'est très rentable.

Ou je pense qu'il est plus utilisable d'utiliser Activité, ou d'autres vitesses de classe dans Activité, pour un médiateur pour la coopération Fragments, car il existe une grande variété de Fragments au cours du cycle de vie à la fois manutention et système. Et il concentre toute cette logique en un seul endroit et rend votre code plus clair.

J'espère que mes considérations vous aideront.

Je ferai de mon mieux pour répondre au mur du texte ici 🙂

Question A:

Les fragments sont conçus pour être des modules réutilisables qui peuvent être branchés et joués avec n'importe quelle activité. En raison de cela, la seule manière correcte d'interagir avec l'activité consiste à faire hériter l'activité d'une interface que le fragment comprend.

 public class MapFragment extends Fragment { private MapFragmentInterface listener; public interface MapFragmentInterface { //All methods to interface with an activity } @Override public void onViewCreated(View view, Bundle savedInstanceState) { // sending the event if (listener != null) listener.anyMethodInTheAboveInterface(); } } 

Ensuite, l'activité implémente l'interface

 public class MainActivity extends Activity implement MapFragmentInterface{ //All methods need to be implemented here } 

Cela permet à votre fragment d'être utilisé avec n'importe quelle activité tant que l'activité implémente cette interface. La raison pour laquelle vous avez besoin de cette interface est que le fragment peut être utilisé avec n'importe quelle activité. Appel d'une méthode comme

 ((TestActivity) getActivity().myCustomMethod(); 

Repose sur le fait que votre fragment ne peut fonctionner que dans une activité de test et donc «briser» les règles des fragments.

Question B et C:

En supposant que vous suivez les directives correctes pour les fragments et qu'ils sont des modules indépendants. Ensuite, vous ne devriez jamais avoir une situation où les fragments doivent se connaître. 99% du temps que les gens pensent avoir besoin de fragments pour communiquer directement, ils peuvent récidiver leur problème à la situation que j'ai donnée ci-dessus en utilisant un patron de MVC ou quelque chose de similaire. Demandez à l'activité d'agir comme le contrôleur et de raconter les fragments lorsqu'ils doivent mettre à jour, puis créer un magasin de données distinct.

coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.