Nous avons vu ensemble, au cours de la première partie, les différents moyens de rendre notre interface utilisateur adaptable en fonction des écrans susceptibles d'afficher notre application, notamment en manipulant nos fichiers de ressources avec les quantificateurs.
Dans cette partie, nous allons voir comment rendre flexible notre interface graphique, en découvrant ensemble le concept de fragment !
J'espère que vous êtes bien réveillés (une bonne tasse de café ne serait pas de trop), car nous allons attaquer maintenant un des concepts les plus importants du développement d'application sous Android.
Qu'est ce qu'un fragment ?
Un peu de contexte...
Au fil des chapitres, lors de la création de nos différentes mini-applications, nous avons créé une activité (MainActivity.java) affichant notre interface graphique via un layout (activity_main.xml).
Cette architecture présente une certaine limite, notamment dès lors que nous disposons d'écrans plutôt grands : nous sommes alors obligés, comme nous l'avons vu, d'adapter notre layout en utilisant différents quantificateurs et créer ainsi autant de fichier activity_main.xml (et de dossierRessources-quantificateurs) que de types d'écrans à gérer. C'est long et fastidieux !
C'est ainsi que dès l'API 11 (Android 3.0) sont apparus les fragments !
Définition et explication
Un fragment peut être représenté comme une partie (ou un... fragment ! :D ) réutilisable de notre interface graphique. Ainsi, en pratique, une activité va être découpée en un ou plusieurs fragments afin de créer une interface utilisateur modulable et surtout flexible visuellement parlant.
Quelques précisions à propos des fragments
Afin de mieux comprendre les fragments dans leur globalité, voici une liste de règles élémentaires (mon cher Watson :soleil: ) à leur sujet :
Les fragments ne sont pas des activités. Cependant ils ne peuvent pas fonctionner seuls, et auront besoin d'être toujours placés à l'intérieur d'une activité.
Vous travaillerez avec les fragments comme avec les activités : ils possèdent un cycle de vie (onCreate, onResume, etc...) et un layout (fragment_main.xml par exemple).
Les fragments sont étroitement liés à une activité, leur cycle de vie aussi. Si l'activité est détruite (rotation de l'écran par exemple), les fragments le seront également. Cependant, vous pourrez ajouter et supprimer des fragments au sein d'une activité à chaud (sans impacter le cycle de vie de l'activité).
Dans une architecture Android MVC avec fragments, l'activité joue le rôle de contrôleur "global", à la manière d'un chef d'orchestre ou d'un capitaine (gestion des communications et de l'affichage des fragments, du système de navigation, etc...) et les fragments jouent le rôle de contrôleur "local" (gestion des vues, des modèles de données, des appels réseaux, etc...).
Pourquoi les utiliser ?
Une des raisons principales d'utiliser les fragments est la volonté de supporter un panel d'écrans de tailles différentes dans son application. Ils permettront ainsi de faciliter l'affichage sur tablette (ainsi que le mode paysage dans certains cas de smartphones à large écran) tout en créant des interfaces réutilisables et indépendantes.
Combinés aux quantificateurs (vus dans la première partie), ils vous permettront de gérer l'ensemble des terminaux Android ! Bonne nouvelle, non ?
Cependant, si vous êtes sûrs et certains que votre application ne s'affichera que sur smartphone, vous pouvez envisager de ne PAS utiliser les fragments (même si avec l'apparition des phablettes comme le Galaxy Note, ce conseil tend à disparaître).
Les fragments (que vous pouvez considérer comme des sous-activités pour plus de simplicité) permettent de découper notre interface utilisateur en petits éléments bien distincts. Cela est très pratique, car si l'on ne peut afficher généralement qu'un seul fragment sur smartphone (par manque cruel de place), on peut en afficher plusieurs sur tablette ! Et ça, c'est agréable pour l'utilisateur ! :ange:
Comment implémenter les fragments ?
Tout simplement à travers une activité. Comme nous l'avons vu tout à l'heure, un fragment ne peut exister qu'à l'intérieur d'une activité. Vous créerez donc un fragment comme une activité, avec sa classe Java et son layout XML :
public class MainFragment extends Fragment {
public MainFragment() { }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.openclassrooms.MainFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</LinearLayout>
Quelques explications :
Vous devez déjà reconnaître quelques similitudes avec la création d'une activité, non ? Déjà, la déclaration du layout ne change absolument pas, ce qui est une bonne chose !
En revanche, notre classe MainFragment hérite de Fragment (à la place de Activity habituellement), afin de récupérer tout le comportement et les propriétés d'un vrai fragment. :) Enfin, en plus de la méthode familière onCreate(), nous avons la méthode onCreateView() qui nous permet de déclarer notre layout (fragment_main).
C'est bien beau tout ça, mais comment notre fragment va-t-il être affiché par notre activité ?
Tout simplement grâce au FragmentManager disponible au sein de chaque activité, véritable couteau-suisse dans la gestion de nos fragments. Pour résumer, c'est lui qui à travers une activité, va ajouter ou supprimer des fragments à la volée.
Un exemple de code déclaré à l'intérieur d'une activité souhaitant afficher un fragment:
//1 - Get our FragmentManager & FragmentTransaction (Inside an activity)
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//2 - Create a new fragment and add it into activty
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Ne vous inquiétez pas si vous ne comprenez pas exactement les lignes précédentes, nous implémenterons tout cela dans les chapitres qui suivent, promis ! ^^
Le cycle de vie d'un fragment
Le plus difficile quand vous utilisez un ou plusieurs fragments au sein d'une activité, c'est de gérer et comprendre correctement leur cycle de vie (ou Lifecycle).
En effet, le cycle de vie d'un fragment est calé sur celui de son activité (en même temps c'est bien normal, puisqu'un fragment est contenu dans une activité... ;) ).
Comme une image vaut mieux que mille mots, voici un schéma (un peu long mais complet) du cycle de vie d'un fragment et d'une activité. Nul besoin de l'apprendre par cœur, essayez simplement de le comprendre, ce qui sera déjà super bien !
Téléchargez l'image à cette adresse.
D'une manière générale, vous n'utiliserez que la méthode onCreateView(), l'équivalent de onCreate() pour une activité, afin de configurer correctement l'ensemble de votre interface graphique.
Mais il est tout de même intéressant de bien comprendre le fonctionnement d'un fragment à l'intérieur d'une activité, non ? ^^
Conclusion
Et voilà ! Dans ce chapitre nous avons découvert les fragments, leur utilité ainsi que leur fonctionnement.
Maintenant que la théorie est terminée, passons à la pratique à travers une série de chapitres portés sur l'implémentation et l'utilisation des fragments.