Jonny Borges
Committed by GitHub

Merge pull request #1031 from kamazoundevz/master

README-fr.md
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
*Idiomas: Español (este archivo), [Indonesio](README.id-ID.md), [Urdu](README.ur-PK.md), [Lengua china](README.zh-cn.md), [Inglés](README.md), [Portugués de Brasil](README.pt-br.md), [Ruso](README.ru.md), [Polaco](README.pl.md), [Coreano](README.ko-kr.md).*
*Idiomas: Español (este archivo), [Indonesio](README.id-ID.md), [Urdu](README.ur-PK.md), [Lengua china](README.zh-cn.md), [Inglés](README.md), [Portugués de Brasil](README.pt-br.md), [Ruso](README.ru.md), [Polaco](README.pl.md), [Coreano](README.ko-kr.md), [Francés](README-fr.md).*
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
... ...
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
**Langues: Français (Ce fichier), [Anglais](README.md), [Indonésien](README.id-ID.md), [Urdu](README.ur-PK.md), [Chinois](README.zh-cn.md), [Portuguais du Brésil](README.pt-br.md), [Espagnol](README-es.md), [Russe](README.ru.md), [Polonais](README.pl.md), [Koréen](README.ko-kr.md).**
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
[![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx)
[![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
<a href="https://github.com/Solido/awesome-flutter">
<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Achetez moi un cafe" style="height: 41px !important;width: 174px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" > </a>
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
- [A Propos de Get](#a-propos-de-get)
- [Installation](#installation)
- [L'application 'Counter' avec GetX](#application-counter-avec-getx)
- [Les trois pilliers](#les-trois-pilliers)
- [Gestion d'état (State management)](#gestion-d-etat)
- [Gestionnaire d'état réactif (Reactive State Manager)](#gestionnaire-d-etat-reactif)
- [Plus de détails sur la gestion d'état](#plus-de-details-sur-la-gestion-d-etat)
- [Gestion de route](#gestion-de-route)
- [Plus de détails sur la gestion de route](#plus-de-details-sur-la-gestion-de-route)
- [Gestion des dépendances](#gestion-des-dependances)
- [Plus de détails sur la gestion des dépendances](#plus-de-details-sur-la-gestion-des-dependances)
- [Utils](#utils)
- [Internationalization](#internationalization)
- [Traductions](#traductions)
- [Utiliser les traductions](#utiliser-les-traductions)
- [Locales](#locales)
- [Changer la locale](#changer-la-locale)
- [Locale du Système](#locale-du-systeme)
- [Changer le Thème](#changer-le-theme)
- [GetConnect](#getconnect)
- [Configuration par défaut](#configuration-par-defaut)
- [Configuration personnalisée](#configuration-personnalisee)
- [Middleware GetPage](#middleware-getpage)
- [Priority](#priority)
- [Redirect](#redirect)
- [onPageCalled](#onpagecalled)
- [OnBindingsStart](#onbindingsstart)
- [OnPageBuildStart](#onpagebuildstart)
- [OnPageBuilt](#onpagebuilt)
- [OnPageDispose](#onpagedispose)
- [Autres APIs](#autres-apis)
- [Paramètres globaux et configurations manuelles facultatifs](#parametres-globaux-et-configurations-manuelles-facultatifs)
- [State Widgets Locaux](#state-widgets-locaux)
- [ValueBuilder](#valuebuilder)
- [ObxValue](#obxvalue)
- [Conseils utiles](#conseils-utiles)
- [GetView](#getview)
- [GetResponsiveView](#getresponsiveview)
- [Guide d'utilisation](#guide-d-utilisation)
- [GetWidget](#getwidget)
- [GetxService](#getxservice)
- [Changements par rapport à 2.0](#changements-par-rapport-a-20)
- [Pourquoi Getx?](#pourquoi-getx)
- [Communité](#communite)
- [Chaînes communautaires](#chaines-communautaires)
- [Comment contribuer](#comment-contribuer)
- [Articles et videos](#articles-et-videos)
# A Propos de Get
- GetX est une solution extra-légère et puissante pour Flutter. Il combine une gestion d'état (state management) de haute performance, une injection de dépendances (dependency injection) intelligente et une gestion de route (route management) rapide et pratique.
- GetX a 3 principes de base. Cela signifie que ces principes sont les priorités pour toutes les ressources de la bibliothèque GetX: **PRODUCTIVITÉ, PERFORMANCE ET ORGANIZATION.**
- **PERFORMANCE:** GetX se concentre sur la performance et la consommation minimale de ressources. GetX n'utilise ni Streams ni ChangeNotifier.
- **PRODUCTIVITÉ:** GetX utilise une syntaxe simple et agréable. Peu importe ce que vous voulez faire, il existe toujours un moyen plus simple avec GetX. Cela économisera des heures de développement et fournira les performances maximales que votre application peut offrir.
En règle générale, le développeur doit s'occuper lui-même de la suppression des contrôleurs de la mémoire. Avec GetX, cela n'est pas nécessaire car les ressources sont, par défaut, supprimées de la mémoire lorsqu'elles ne sont pas utilisées. Si vous souhaitez les conserver en mémoire, vous devez déclarer explicitement "permanent: true" comme paramètre lors de la création de la ressource. De cette façon, en plus de gagner du temps, vous risquez moins d'avoir des ressources inutiles dans la mémoire. L'initialisation des ressources est également 'lazy' par défaut (i.e. se fait seulement lorsque la ressource est nécessaire).
- **ORGANIZATION:** GetX permet le découplage total de la Vue (View), de la Logique de Présentation (Presentation Logic), de la Business Logic, de l'injection de dépendances (Dependency Injection) et de la Navigation. Vous n'avez pas besoin de contexte pour naviguer entre les routes, vous n'êtes donc pas dépendant de la hiérarchisation des widgets (visualisation) pour cela. Vous n'avez pas besoin de 'context' pour accéder à vos contrôleurs/blocs via un inheritedWidget, vous dissociez donc complètement votre logique de présentation (Vue) et votre Business logic de votre couche de visualisation. Vous n'avez pas besoin d'injecter vos classes Controlleûrs / Modèles / Blocs le long de la hiérarchie de Widgets via `MultiProvider`. Pour cela, GetX utilise sa propre fonction d'injection de dépendances (DI), découplant complètement la DI de sa Vue.
Avec GetX, vous savez où trouver chaque module de votre application, avec un code propre par défaut. En plus de rendre la maintenance facile, cela rend le partage de modules quelque chose qui jusque-là dans Flutter était impensable, quelque chose de totalement possible.
BLoC était un point de départ pour organiser le code dans Flutter, il sépare la Business logic de la visualisation. GetX en est une évolution naturelle, séparant non seulement la Business logic mais aussi la logique de présentation. L'injection de dépendances et les routes sont également découplées, et la couche de données est séparée du tout. Vous savez où tout se trouve, et tout cela d'une manière plus facile que de construire un 'Hello World''.
GetX est le moyen le plus simple, pratique et évolutif de créer des applications hautes performances avec le SDK Flutter. Il possède un vaste écosystème qui fonctionne parfaitement, c'est facile pour les débutants et précis pour les experts. Il est sécurisé, stable, à jour et offre une vaste gamme d'API intégrées qui ne sont pas présentes dans le SDK Flutter par défaut.
- GetX possède une multitude de fonctionnalités qui vous permettent de démarrer la programmation sans vous soucier de quoi que ce soit, mais chacune de ces fonctionnalités se trouve dans des conteneurs séparés et ne démarre qu'après utilisation. Si vous n'utilisez que la gestion des états (State Management), seule la gestion des états sera compilée. Si vous n'utilisez que des routes, rien de la gestion d'état ne sera compilé.
- GetX a un énorme écosystème, une grande communauté, un grand nombre de collaborateurs, et sera maintenu tant que Flutter existera. GetX est également capable de fonctionner avec le même code sur Android, iOS, Web, Mac, Linux, Windows et sur votre serveur. Il est possible de réutiliser entièrement votre code créé sur le frontend et le backend avec Get Server.
**Il est possible d'entièrement réutiliser votre code écrit sur le frontend, pour le backend avec [Get Server](https://github.com/jonataslaw/get_server)**.
**De plus, l'ensemble du processus de développement peut être complètement automatisé, à la fois sur le serveur et sur le front-end avec [Get CLI](https://github.com/jonataslaw/get_cli)**.
**De plus, pour augmenter encore votre productivité, nous avons l'[extension pour VSCode](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) et l'[extension pour Android Studio/Intellij](https://plugins.jetbrains.com/plugin/14975-getx-snippets)**
# Installation
Ajoutez Get à votre fichier pubspec.yaml:
```yaml
dependencies:
get:
```
Importez Get dans les fichiers dans lesquels il doit être utilisé:
```dart
import 'package:get/get.dart';
```
# Application Counter avec Getx
Le projet "Counter" créé par défaut sur chaque nouveau projet Flutter comporte plus de 100 lignes (avec commentaires). Pour montrer la puissance de Get, je vais vous montrer comment faire un "compteur" changeant d'état à chaque clic, naviguer entre les pages et partager l'état entre les écrans, le tout de manière organisée, en séparant la Business logic de la Vue, en SEULEMENT 26 LIGNES DE CODE INCLUANT LES COMMENTAIRES.
- Step 1:
Ajoutez "Get" avant MaterialApp, pour le transformer en GetMaterialApp
```dart
void main() => runApp(GetMaterialApp(home: Home()));
```
- Note: cela ne modifie pas le MaterialApp de Flutter, GetMaterialApp n'est pas un MaterialApp modifié, il s'agit simplement d'un widget préconfiguré, qui a le MaterialApp par défaut comme enfant (child: ). Vous pouvez le configurer manuellement, mais ce n'est certainement pas nécessaire. GetMaterialApp créera des routes, les injectera, injectera les traductions, injectera tout ce dont vous avez besoin pour la navigation de routes. Si vous utilisez Get uniquement pour la gestion de l'état (State management) ou la gestion des dépendances (DI), il n'est pas nécessaire d'utiliser GetMaterialApp. GetMaterialApp est nécessaire pour les routes, les 'snackbars', l'internationalisation, les 'bottomSheets', les dialogues et les API de haut niveau liés aux routes et à l'absence de 'context'.
- Note²: Cette étape n'est nécessaire que si vous allez utiliser la gestion de routes (Get.to(), Get.back(), etc). Si vous ne l'utiliserez pas, il n'est pas nécessaire de faire l'étape 1.
- Step 2:
Créez votre classe de Business logic et placez-y toutes les variables, méthodes et contrôleurs.
Vous pouvez rendre toute variable observable en utilisant un simple ".obs".
```dart
class Controller extends GetxController{
var count = 0.obs;
increment() => count++;
}
```
- Step 3:
Créez votre Vue, utilisez StatelessWidget et économisez de la RAM, avec Get, vous n'aurez peut-être plus besoin d'utiliser StatefulWidget.
```dart
class Home extends StatelessWidget {
@override
Widget build(context) {
// Instanciez votre classe en utilisant Get.put() pour le rendre disponible pour tous les routes "descendantes".
final Controller c = Get.put(Controller());
return Scaffold(
// Utilisez Obx(()=> pour mettre à jour Text() chaque fois que count est changé.
appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
// Remplacez les 8 lignes Navigator.push par un simple Get.to(). Vous n'avez pas besoin de 'context'
body: Center(child: RaisedButton(
child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
}
}
class Other extends StatelessWidget {
// Vous pouvez demander à Get de trouver un contrôleur utilisé par une autre page et de vous y rediriger.
final Controller c = Get.find();
@override
Widget build(context){
// Accéder à la variable 'count' qui est mise à jour
return Scaffold(body: Center(child: Text("${c.count}")));
}
}
```
Résultat:
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
C'est un projet simple mais il montre déjà à quel point Get est puissant. Au fur et à mesure que votre projet se développe, cette différence deviendra plus significative.
Get a été conçu pour fonctionner avec des équipes, mais il simplifie le travail d'un développeur individuel.
Améliorez vos délais, livrez tout à temps sans perte de performances. Get n'est pas pour tout le monde, mais si vous vous êtes identifié à cette phrase, Get est fait pour vous!
# Les trois pilliers
## Gestion d Etat
Get a deux gestionnaires d'état différents: le gestionnaire d'état simple (nous l'appellerons GetBuilder) et le gestionnaire d'état réactif (GetX / Obx).
### Gestionnaire d Etat Reactif
La programmation réactive peut aliéner de nombreuses personnes car on dit qu'elle est compliquée. GetX fait de la programmation réactive quelque chose d'assez simple:
- Vous n'aurez pas besoin de créer des StreamControllers.
- Vous n'aurez pas besoin de créer un StreamBuilder pour chaque variable
- Vous n'aurez pas besoin de créer une classe pour chaque état.
- Vous n'aurez pas besoin de créer un 'get' pour une valeur initiale.
- Vous n'aurez pas besoin d'utiliser des générateurs de code
La programmation réactive avec Get est aussi simple que d'utiliser setState.
Imaginons que vous ayez une variable 'name' et que vous souhaitiez que chaque fois que vous la modifiez, tous les widgets qui l'utilisent soient automatiquement modifiés.
Voici votre variable:
```dart
var name = 'Jonatas Borges';
```
Pour la rendre observable, il vous suffit d'ajouter ".obs" à la fin:
```dart
var name = 'Jonatas Borges'.obs;
```
Et dans l'interface utilisateur, lorsque vous souhaitez afficher cette valeur et mettre à jour l'écran chaque fois qu'elle change, faites simplement:
```dart
Obx(() => Text("${controller.name}"));
```
C'est _tout_. Si simple que ca.
### Plus de details sur la gestion d Etat
**Lire une explication plus approfondie de la gestion d'état [ici](./documentation/fr_FR/state_management.md). Là-bas, vous verrez plus d'exemples surtout pour la différence entre le gestionnaire d'état simple et le gestionnaire d'état réactif.**
Vous pourrez vous faire une meilleure idée de la puissance de GetX.
## Gestion de route
Si vous envisagez d'utiliser des routes/snackbars/dialogs/bottomsheets sans 'context', GetX est également excellent pour vous, voyez par vous-même:
Ajoutez "Get" avant votre MaterialApp, en le transformant en GetMaterialApp
```dart
GetMaterialApp( // Avant: MaterialApp(
home: MyHome(),
)
```
Accédez à un nouvel écran:
```dart
Get.to(ÉcranSuivant());
```
Accédez au nouvel écran par le nom. Voir plus de détails sur les itinéraires nommés (named routes) [ici](./documentation/fr_FR/route_management.md#navigation-avec-des-itinraires-nomms)
```dart
Get.toNamed('/details');
```
Pour fermer des snackbars, dialogs, bottomsheets, ou tout ce que vous auriez normalement fermé avec Navigator.pop(context);
```dart
Get.back();
```
Pour aller à l'écran suivant avec aucune option pour revenir à l'écran précédent (pour une utilisation dans SplashScreens, écrans de connexion, etc.)
```dart
Get.off(NextScreen());
```
Pour aller à l'écran suivant et annuler tous les itinéraires précédents (utile dans les paniers d'achat en ligne, les sondages et les tests)
```dart
Get.offAll(NextScreen());
```
Avez-vous remarqué que vous n'avez eu besoin d'utiliser 'context' pour aucune de ces opérations? C'est l'un des plus grands avantages de l'utilisation de la gestion de route avec Get. Avec cela, vous pouvez appeler toutes ces méthodes à partir de votre classe de contrôleur, sans soucis.
### Plus de details sur la gestion de route
**Get fonctionne avec des itinéraires nommés (named routes) et offre également un contrôle plus granulaire de vos routes! Il y a une documentation approfondie [ici](./documentation/fr_FR/route_management.md)**
## Gestion des dependances
Get a un gestionnaire de dépendances (dependency manager) simple et puissant qui vous permet de récupérer la même classe que votre Bloc ou Controller avec seulement 1 ligne de code, pas de 'context' Provider, pas d'inheritedWidget:
```dart
Controller controller = Get.put(Controller()); // Au lieu de Controller controller = Controller();
```
- Remarque: Si vous utilisez le gestionnaire d'état de Get, accordez plus d'attention à l'API 'Bindings', qui facilitera la connexion de vos Vues à vos contrôleurs.
Au lieu d'instancier votre classe dans la classe que vous utilisez, vous l'instanciez dans l'instance Get, ce qui la rendra disponible dans toute votre application.
Vous pouvez donc utiliser votre contrôleur (ou classe Bloc) normalement.
**Conseil:** La gestion des dépendances est découplée des autres parties du package, donc si, par exemple, votre application utilise déjà un gestionnaire d'état (n'importe lequel, peu importe), vous n'avez pas besoin de tout réécrire, vous pouvez l'utiliser avec l'injection de dépendance de Get sans aucun problème.
```dart
controller.fetchApi();
```
Imaginez que vous ayez parcouru de nombreuses routes et que vous ayez besoin de données qui ont été laissées dans votre contrôleur, vous auriez besoin d'un gestionnaire d'état combiné avec le 'Provider' ou 'Get_it', n'est-ce pas? Pas avec Get. Il vous suffit de demander à Get de "trouver" votre contrôleur, vous n'avez pas besoin de dépendances supplémentaires:
```dart
Controller controller = Get.find();
//Oui, cela ressemble à de la magie. Get trouvera votre contrôleur et vous le livrera. Vous pouvez avoir 1 million de contrôleurs instanciés, Get vous retournera toujours le bon contrôleur.
```
Et puis vous pourrez récupérer les données de votre contrôleur obtenu précédemment:
```dart
Text(controller.textFromApi);
```
### Plus de details sur la gestion des dependances
**Trouvez une explication plus détaillée sur la gestion des dépendances [ici](./documentation/fr_FR/dependency_management.md)**
# Utils
## Internationalization
### Traductions
Les traductions sont enregistrées sous forme de dictionaire clé-valeur simple.
Pour ajouter des traductions, créez une classe qui 'extend' `Translations`.
```dart
import 'package:get/get.dart';
class Messages extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'en_US': {
'hello': 'Hello World',
},
'de_DE': {
'hello': 'Hallo Welt',
}
};
}
```
#### Utiliser les traductions
Ajouter juste `.tr` à la clé et elle sera traduite selon la valeur actuelle `Get.locale` et de `Get.fallbackLocale`.
```dart
Text('title'.tr);
```
#### Utiliser les traductions avec le singulier et le pluriel
```dart
var products = [];
Text('cléAuSingulier'.trPlural('cléAuPluriel', products.length, Args));
```
#### Utiliser les traductions avec paramètres
```dart
import 'package:get/get.dart';
Map<String, Map<String, String>> get keys => {
'en_US': {
'logged_in': 'logged in as @name with email @email',
},
'es_ES': {
'logged_in': 'iniciado sesión como @name con e-mail @email',
}
};
Text('logged_in'.trParams({
'name': 'Jhon',
'email': 'jhon@example.com'
}));
```
### Locales
'Locales' signifie lieux.
Pour definir les traductions, passer les paramètres 'locale' et 'translations' à GetMaterialApp.
```dart
return GetMaterialApp(
translations: Messages(), // Vos traductions
locale: Locale('en', 'US'), // Les traductions seront faites dans cette 'locale' (langue)
fallbackLocale: Locale('en', 'UK'), // definit le 'language de secours' au cas oú un language invalide est sélectionné.
);
```
#### Changer la locale
Appelez `Get.updateLocale (locale)` pour mettre à jour la locale. Les traductions utilisent alors automatiquement la nouvelle langue.
```dart
var locale = Locale('en', 'US');
Get.updateLocale(locale);
```
#### Locale du systeme
Pour lire les paramètres régionaux ('locales') du système, vous pouvez utiliser `Get.deviceLocale`.
```dart
return GetMaterialApp(
locale: Get.deviceLocale,
);
```
## Changer le Theme
Veuillez ne pas utiliser de widget de niveau supérieur à `GetMaterialApp` pour le mettre à jour. Cela peut créer des clés ('keys') en double. Beaucoup de gens sont habitués à l'approche préhistorique de la création d'un widget "ThemeProvider" juste pour changer le thème de votre application, et ce n'est certainement PAS nécessaire avec **GetX ™**.
Vous pouvez créer votre thème personnalisé et l'ajouter simplement dans `Get.changeTheme` sans aucune préconfiguration pour cela:
```dart
Get.changeTheme(ThemeData.light());
```
Si vous voulez créer quelque chose comme un bouton qui change le thème dans `onTap`, vous pouvez combiner deux API **GetX ™** pour cela:
- L'API qui vérifie si le "Thème" sombre est utilisé.
- Et l'API de changement de thème, vous pouvez simplement le mettre dans un 'onPressed':
```dart
Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());
```
Lorsque 'onPressed' est appelé, si `.darkmode` est activé, il passera au _thème clair_, et lorsque le _thème clair_ est actif, il passera au _thème sombre_.
## GetConnect
GetConnect est un moyen facile de communiquer de votre backend à votre frontend avec http ou websockets.
### Configuration par defaut
Vous pouvez simplement 'extends' GetConnect et utiliser les méthodes GET / POST / PUT / DELETE / SOCKET pour communiquer avec votre API Rest ou vos websockets.
```dart
class UserProvider extends GetConnect {
// Get request
Future<Response> getUser(int id) => get('http://youapi/users/$id');
// Post request
Future<Response> postUser(Map data) => post('http://youapi/users', body: data);
// Post request with File
Future<Response<CasesModel>> postCases(List<int> image) {
final form = FormData({
'file': MultipartFile(image, filename: 'avatar.png'),
'otherFile': MultipartFile(image, filename: 'cover.png'),
});
return post('http://youapi/users/upload', form);
}
GetSocket userMessages() {
return socket('https://yourapi/users/socket');
}
}
```
### Configuration personnalisee
GetConnect est hautement personnalisable. Vous pouvez définir l'URL de base, comme modificateurs de réponse, comme modificateurs de requêtes, définir un authentificateur, et même le nombre de tentatives oú il tentera de s'authentifier, en plus de donner la possibilité de définir un décodeur standard qui transformera toutes vos Requêtes dans vos Modèles sans aucune configuration supplémentaire.
```dart
class HomeProvider extends GetConnect {
@override
void onInit() {
// Toute 'Request' passera à jsonEncode donc CasesModel.fromJson()
httpClient.defaultDecoder = CasesModel.fromJson;
httpClient.baseUrl = 'https://api.covid19api.com';
// baseUrl = 'https://api.covid19api.com';
// Il définit baseUrl pour Http et websockets si utilisé sans instance [httpClient]
// Cela attachera la propriété 'apikey' sur l'en-tête ('header') de toutes les 'request's
httpClient.addRequestModifier((request) {
request.headers['apikey'] = '12345678';
return request;
});
// Même si le serveur envoie des données avec le pays "Brésil",
// cela ne sera jamais affiché aux utilisateurs, car vous supprimez
// ces données de la réponse, même avant que la réponse ne soit délivrée
httpClient.addResponseModifier<CasesModel>((request, response) {
CasesModel model = response.body;
if (model.countries.contains('Brazil')) {
model.countries.remove('Brazil');
}
});
httpClient.addAuthenticator((request) async {
final response = await get("http://yourapi/token");
final token = response.body['token'];
// Définit l'en-tête
request.headers['Authorization'] = "$token";
return request;
});
// L'Autenticator sera appelé 3 fois si HttpStatus est HttpStatus.unauthorized
httpClient.maxAuthRetries = 3;
}
@override
Future<Response<CasesModel>> getCases(String path) => get(path);
}
```
## Middleware GetPage
GetPage a maintenant une nouvelle propriété qui prend une liste de GetMiddleWare et les exécute dans l'ordre spécifique.
**Note**: Lorsque GetPage a un Middleware, tous les enfants de cette page auront automatiquement les mêmes middlewares.
### Priority
L'ordre des middlewares à exécuter peut être défini par la priorité dans GetMiddleware.
```dart
final middlewares = [
GetMiddleware(priority: 2),
GetMiddleware(priority: 5),
GetMiddleware(priority: 4),
GetMiddleware(priority: -8),
];
```
ces middlewares seront exécutés dans cet ordre **-8 => 2 => 4 => 5**
### Redirect
Cette fonction sera appelée lors de la recherche de la page de l'itinéraire appelé. Elle reçoit RouteSettings comme résultat vers oú rediriger. Sinon donnez-lui la valeur null et il n'y aura pas de redirection.
```dart
GetPage redirect( ) {
final authService = Get.find<AuthService>();
return authService.authed.value ? null : RouteSettings(name: '/login');
}
```
### onPageCalled
Cette fonction sera appelée lorsque cette page sera appelée.
Vous pouvez l'utiliser pour changer quelque chose sur la page ou lui donner une nouvelle page.
```dart
GetPage onPageCalled(GetPage page) {
final authService = Get.find<AuthService>();
return page.copyWith(title: 'Welcome ${authService.UserName}');
}
```
### OnBindingsStart
Cette fonction sera appelée juste avant l'initialisation des liaisons ('bidings').
Ici, vous pouvez modifier les liaisons de cette page.
```dart
List<Bindings> onBindingsStart(List<Bindings> bindings) {
final authService = Get.find<AuthService>();
if (authService.isAdmin) {
bindings.add(AdminBinding());
}
return bindings;
}
```
### OnPageBuildStart
Cette fonction sera appelée juste après l'initialisation des liaisons ('bidings').
Ici, vous pouvez faire quelque chose après avoir créé les liaisons et avant de créer le widget de page.
```dart
GetPageBuilder onPageBuildStart(GetPageBuilder page) {
print('les liaisons sont prêtes');
return page;
}
```
### OnPageBuilt
Cette fonction sera appelée juste après l'appel de la fonction GetPage.page et vous donnera le résultat de la fonction et prendra le widget qui sera affiché.
### OnPageDispose
Cette fonction sera appelée juste après avoir disposé tous les objets associés (contrôleurs, vues, ...) à la page.
## Autres APIs
```dart
// donne les arguments actuels de currentScreen
Get.arguments
// donne le nom de l'itinéraire précédent
Get.previousRoute
// donne la route brute d'accès par exemple, rawRoute.isFirst()
Get.rawRoute
// donne accès à l'API de routing de GetObserver
Get.routing
// vérifier si le snackbar est ouvert
Get.isSnackbarOpen
// vérifier si la boîte de dialogue est ouverte
Get.isDialogOpen
// vérifie si la bottomSheet est ouverte
Get.isBottomSheetOpen
// supprime une route.
Get.removeRoute()
// retourne à plusieurs reprises jusqu'à ce que le prédicat retourne 'true'.
Get.until()
// passe à la route suivante et supprime toutes les routes précédentes jusqu'à ce que le prédicat retourne 'true'.
Get.offUntil()
// passe à la route nommée suivante et supprime toutes les routes précédentes jusqu'à ce que le prédicat retourne 'true'.
Get.offNamedUntil()
// Vérifie sur quelle plate-forme l'application s'exécute
GetPlatform.isAndroid
GetPlatform.isIOS
GetPlatform.isMacOS
GetPlatform.isWindows
GetPlatform.isLinux
GetPlatform.isFuchsia
// Vérifie le type d'appareil
GetPlatform.isMobile
GetPlatform.isDesktop
// Toutes les plates-formes sont prises en charge indépendamment, dans le Web!
// Vous pouvez dire si vous utilisez un navigateur
// sur Windows, iOS, OSX, Android, etc.
GetPlatform.isWeb
// Équivaut à: MediaQuery.of(context).size.height,
// mais immuable.
Get.height
Get.width
// Donne le 'context' actuel de 'Navigator'.
Get.context
// Donne le contexte du snackbar / dialogue / bottomsheet au premier plan, n'importe où dans votre code.
Get.contextOverlay
// Remarque: les méthodes suivantes sont des extensions sur le 'context'. Puisque vous
// avez accès au contexte à n'importe quel endroit de votre interface utilisateur, vous pouvez l'utiliser n'importe où dans le code de l'interface utilisateur
// Si vous avez besoin d'une hauteur / largeur variable (comme les fenêtres de bureau ou de navigateur qui peuvent être mises à l'échelle), vous devrez utiliser le contexte.
context.width
context.height
// Vous donne le pouvoir de définir la moitié de l'écran, un tiers de celui-ci et ainsi de suite.
// Utile pour les applications responsives.
// paramètre dividedBy (double) optionnel - par défaut: 1
// paramètre reducedBy (double) facultatif - par défaut: 0
context.heightTransformer ()
context.widthTransformer ()
/// Similaire à MediaQuery.of(context).size
context.mediaQuerySize()
/// Similaire à MediaQuery.of(context).padding
context.mediaQueryPadding()
/// Similaire à MediaQuery.of(context).viewPadding
context.mediaQueryViewPadding()
/// Similaire à MediaQuery.of(context).viewInsets;
context.mediaQueryViewInsets()
/// Similaire à MediaQuery.of(context).orientation;
context.orientation()
/// Vérifie si l'appareil est en mode paysage
context.isLandscape()
/// Vérifie si l'appareil est en mode portrait
context.isPortrait()
/// Similaire à MediaQuery.of(context).devicePixelRatio;
context.devicePixelRatio()
/// Similaire à MediaQuery.of(context).textScaleFactor;
context.textScaleFactor()
/// Obtenir le côté le plus court de l'écran
context.mediaQueryShortestSide()
/// Vrai si la largeur est supérieure à 800p
context.showNavbar()
/// Vrai si le côté le plus court est inférieur à 600p
context.isPhone()
/// Vrai si le côté le plus court est plus grand que 600p
context.isSmallTablet()
/// Vrai si le côté le plus court est plus grand que 720p
context.isLargeTablet()
/// Vrai si l'appareil actuel est une tablette
context.isTablet()
/// Renvoie une valeur <T> en fonction de la taille de l'écran
/// peut donner une valeur pour:
/// watch: si le côté le plus court est inférieur à 300
/// mobile: si le côté le plus court est inférieur à 600
/// tablette: si le côté le plus court est inférieur à 1200
/// bureautique: si la largeur est supérieure à 1200
context.responsiveValue<T>()
```
### Parametres globaux et configurations manuelles facultatifs
GetMaterialApp configure tout pour vous, mais si vous souhaitez configurer Get manuellement:
```dart
MaterialApp(
navigatorKey: Get.key,
navigatorObservers: [GetObserver()],
);
```
Vous pourrez également utiliser votre propre middleware dans `GetObserver`, cela n'influencera rien.
```dart
MaterialApp(
navigatorKey: Get.key,
navigatorObservers: [
GetObserver(MiddleWare.observer) // Ici
],
);
```
Vous pouvez créer _Global Settings_ pour `Get`. Ajoutez simplement `Get.config` à votre code avant de changer de route.
Ou faites-le directement dans votre `GetMaterialApp`
```dart
GetMaterialApp(
enableLog: true,
defaultTransition: Transition.fade,
opaqueRoute: Get.isOpaqueRouteDefault,
popGesture: Get.isPopGestureEnable,
transitionDuration: Get.defaultDurationTransition,
defaultGlobalState: Get.defaultGlobalState,
);
Get.config(
enableLog = true,
defaultPopGesture = true,
defaultTransition = Transitions.cupertino
)
```
Vous pouvez éventuellement rediriger tous les messages de journalisation (logging) de `Get`.
Si vous souhaitez utiliser votre propre package de journalisation préféré,
et souhaitez capturer les logs là-bas:
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// transmettez le message à votre package de journalisation préféré ici
// veuillez noter que même si enableLog: false, les messages du journal seront poussés dans ce 'callback'
// vérifiez le 'flag' si vous le souhaitez via GetConfig.isLogEnable
}
```
### State Widgets Locaux
Ces Widgets vous permettent de gérer une valeur unique, et de garder l'état éphémère et localement.
Nous avons des saveurs pour réactif et simple.
Par exemple, vous pouvez les utiliser pour basculer obscureText dans un `TextField`, peut-être créer un
Panneau extensible, ou peut-être modifier l'index actuel dans `BottomNavigationBar` tout en modifiant le contenu
de 'body' dans un `Scaffold`.
#### ValueBuilder
Une simplification de `StatefulWidget` qui fonctionne avec un callback `.setState` qui prend la valeur mise à jour.
```dart
ValueBuilder<bool>(
initialValue: false,
builder: (value, updateFn) => Switch(
value: value,
onChanged: updateFn, // même signature! vous pouvez utiliser (newValue) => updateFn (newValue)
),
// si vous devez appeler quelque chose en dehors de la méthode du builder.
onUpdate: (value) => print("Valeur mise à jour: $value"),
onDispose: () => print("Widget détruit"),
),
```
#### ObxValue
Similaire à [`ValueBuilder`](#valuebuilder), mais c'est la version Reactive, vous passez une instance Rx (rappelez-vous les .obs magiques?) et il
se met à jour automatiquement ... n'est-ce pas génial?
```dart
ObxValue((data) => Switch(
value: data.value,
onChanged: data, // Rx a une fonction _callable_! Vous pouvez utiliser (flag) => data.value = flag,
),
false.obs,
),
```
## Conseils utiles
`.obs`ervables (également appelés types _Rx_) ont une grande variété de méthodes et d'opérateurs internes.
> Il est très courant de croire qu'une propriété avec `.obs` ** EST ** la valeur réelle ... mais ne vous y trompez pas!
> Nous évitons la déclaration Type de la variable, car le compilateur de Dart est assez intelligent, et le code
> semble plus propre, mais:
```dart
var message = 'Hello world'.obs;
print( 'Message "$message" est de Type ${message.runtimeType}');
```
Bien que `message` _prints_ la vraie valeur du String, le Type est **RxString**!
Donc, vous ne pouvez pas faire `message.substring( 0, 4 )`.
Vous devez utiliser la vraie `valeur` dans _observable_:
La façon "la plus utilisée" est `.value`, mais, que vous pouviez aussi...
```dart
final name = 'GetX'.obs;
// "met à jour" le flux, uniquement si la valeur est différente de la valeur actuelle.
name.value = 'Hey';
// Toutes les propriétés Rx sont "appelables" et renvoie la nouvelle valeur.
// mais cette approche n'accepte pas `null`, l'interface utilisateur ne sera pas reconstruite.
name('Hello');
// est comme un getter, affiche `Hello`.
name() ;
/// nombres:
final count = 0.obs;
// Vous pouvez utiliser toutes les opérations non mutables à partir de num primitives!
count + 1;
// Fais attention! ceci n'est valable que si `count` n'est pas final, mais var
count += 1;
// Vous pouvez également comparer avec des valeurs:
count > 2;
/// booleans:
final flag = false.obs;
// bascule la valeur entre true / false
flag.toggle();
/// tous les types:
// Définit la `valeur` sur null.
flag.nil();
// Toutes les opérations toString (), toJson () sont transmises à la `valeur`
print( count ); // appelle `toString ()` à l'intérieur de RxInt
final abc = [0,1,2].obs;
// Convertit la valeur en un Array json, affiche RxList
// Json est pris en charge par tous les types Rx!
print('json: ${jsonEncode(abc)}, type: ${abc.runtimeType}');
// RxMap, RxList et RxSet sont des types Rx spéciaux, qui étendent leurs types natifs.
// mais vous pouvez travailler avec une liste comme une liste régulière, bien qu'elle soit réactive!
abc.add(12); // pousse 12 dans la liste et MET À JOUR le flux.
abc[3]; // comme Lists, lit l'index 3.
// l'égalité fonctionne avec le Rx et la valeur, mais hashCode est toujours pris à partir de la valeur
final number = 12.obs;
print( number == 12 ); // retource > true
/// Modèles Rx personnalisés:
// toJson (), toString () sont différés à l'enfant, vous pouvez donc implémenter 'override' sur eux, et print() l'observable directement.
class User {
String name, last;
int age;
User({this.name, this.last, this.age});
@override
String toString() => '$name $last, $age ans';
}
final user = User(name: 'John', last: 'Doe', age: 33).obs;
// `user` est" réactif ", mais les propriétés à l'intérieur NE SONT PAS!
// Donc, si nous changeons une variable à l'intérieur ...
user.value.name = 'Roi';
// Le widget ne se reconstruira pas !,
// `Rx` n'a aucun indice lorsque vous changez quelque chose à l'intérieur de l'utilisateur.
// Donc, pour les classes personnalisées, nous devons "notifier" manuellement le changement.
user.refresh();
// ou utiliser `update()`!
user.update((value){
value.name='Roi';
});
print( user );
```
#### GetView
J'adore ce widget. Si simple, mais si utile!
C'est un widget `const Stateless` qui a un getter` controller` pour un `Controller` enregistré, c'est tout.
```dart
class AwesomeController extends GetxController {
final String title = 'My Awesome View';
}
// N'oubliez PAS de passer le `Type` que vous avez utilisé pour enregistrer votre contrôleur!
class AwesomeView extends GetView<AwesomeController> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(20),
child: Text(controller.title), // appelez `controller.quelqueChose`
);
}
}
```
#### GetResponsiveView
Étendez ce widget pour créer une vue réactive.
ce widget contient la propriété `screen` qui a toutes les
informations sur la taille et le type de l'écran.
##### Guide d utilisation
Vous avez deux options pour le créer:
- avec la méthode `builder` vous renvoyez le widget à construire.
- avec les méthodes `desktop`,` tablet`, `phone`,` watch`. la méthode spécifique sera exécutée lorsque le type d'écran correspond à la méthode.
Lorsque l'écran est [ScreenType.Tablet], la méthode `tablet` sera exécutée et ainsi de suite.
**Note:** Si vous utilisez cette méthode, veuillez définir la propriété `alwaysUseBuilder` à `false`
Avec la propriété `settings`, vous pouvez définir la limite de largeur pour les types d'écran.
![exemple](https://github.com/SchabanBo/get_page_example/blob/master/docs/Example.gif?raw=true)
Code pour cet écran
[code](https://github.com/SchabanBo/get_page_example/blob/master/lib/pages/responsive_example/responsive_view.dart)
#### GetWidget
La plupart des gens n'ont aucune idée de ce widget ou confondent totalement son utilisation.
Le cas d'utilisation est très rare, mais très spécifique: il `met en cache` un contrôleur.
En raison du _cache_, ne peut pas être un `const Stateless`.
> Alors, quand avez-vous besoin de "mettre en cache" un contrôleur?
Si vous utilisez, une autre fonctionnalité "pas si courante" de **GetX**: `Get.create()`.
`Get.create(()=>Controller())` générera un nouveau `Controller` chaque fois que vous appelez
`Get.find<Controller>()`.
C'est là que `GetWidget` brille ... comme vous pouvez l'utiliser, par exemple,
pour conserver une liste de <Todo>s. Donc, si le widget est "reconstruit", il conservera la même instance de contrôleur.
#### GetxService
Cette classe est comme un `GetxController`, elle partage le même cycle de vie ( `onInit()`, `onReady()`, `onClose()`), mais n'a pas de "logique" en elle.
Il notifie simplement le **GetX** Dependency Injection system, que cette sous-classe
**ne peut pas** être supprimé de la mémoire.
Donc est très utile pour garder vos "Services" toujours à portée de main et actifs avec `Get.find()`. Comme:
`ServiceAPI`, `ServiceDeSauvegarde`, `ServiceDeCaching`.
```dart
Future<void> main() async {
await initServices(); /// Attend l'initialisation des services.
runApp(SomeApp());
}
/// Est une démarche intelligente pour que vos services s'initialisent avant d'exécuter l'application Flutter.
/// car vous pouvez contrôler le flux d'exécution (peut-être devez-vous charger une configuration de thème,
/// apiKey, langue définie par l'utilisateur ... donc chargez SettingService avant d'exécuter ApiService.
/// donc GetMaterialApp () n'a pas besoin de se reconstruire et prend les valeurs directement.
void initServices() async {
print('starting services ...');
/// C'est ici que vous mettez get_storage, hive, shared_pref initialization.
/// ou les connexions moor, ou autres choses async.
await Get.putAsync(() => DbService().init());
await Get.putAsync(SettingsService()).init();
print('Tous les services ont démarré...');
}
class DbService extends GetxService {
Future<DbService> init() async {
print('$runtimeType retarde de 2 sec');
await 2.delay();
print('$runtimeType prêts!');
return this;
}
}
class SettingsService extends GetxService {
void init() async {
print("$runtimeType retarde d'1 sec");
await 1.delay();
print('$runtimeType prêts!');
}
}
```
La seule façon de supprimer réellement un `GetxService`, est d'utiliser` Get.reset () `qui est comme un
"Hot Reboot" de votre application. N'oubliez donc pas que si vous avez besoin d'une persistance absolue d'une instance de classe
durée de vie de votre application, utilisez `GetxService`.
# Changements par rapport a 2.0
1- Types Rx:
| Avant | Après |
| ------- | ---------- |
| StringX | `RxString` |
| IntX | `RxInt` |
| MapX | `RxMap` |
| ListX | `RxList` |
| NumX | `RxNum` |
| DoubleX | `RxDouble` |
RxController et GetBuilder ont maintenant fusionné, vous n'avez plus besoin de mémoriser le contrôleur que vous souhaitez utiliser, utilisez simplement GetxController, cela fonctionnera pour une gestion simple de l'état et également pour la réactivité.
2- NamedRoutes
Avant:
```dart
GetMaterialApp(
namedRoutes: {
'/': GetRoute(page: Home()),
}
)
```
Maintenant:
```dart
GetMaterialApp(
getPages: [
GetPage(name: '/', page: () => Home()),
]
)
```
Pourquoi ce changement?
Souvent, il peut être nécessaire de décider quelle page sera affichée à partir d'un paramètre, ou d'un 'login token', l'approche précédente était inflexible, car elle ne le permettait pas.
L'insertion de la page dans une fonction a considérablement réduit la consommation de RAM, puisque les routes ne seront pas allouées en mémoire depuis le démarrage de l'application, et cela a également permis de faire ce type d'approche:
```dart
GetStorage box = GetStorage();
GetMaterialApp(
getPages: [
GetPage(name: '/', page:(){
return box.hasData('token') ? Home() : Login();
})
]
)
```
# Pourquoi Getx?
1- Plusieurs fois après une mise à jour de Flutter, plusieurs de vos packages seront invalides. Parfois, des erreurs de compilation se produisent, des erreurs apparaissent souvent pour lesquelles il n'y a toujours pas de réponses, et le développeur doit savoir d'où vient l'erreur, suivre l'erreur, puis seulement essayer d'ouvrir un problème dans le référentiel correspondant et voir son problème résolu. Get centralise les principales ressources pour le développement (gestion des états, des dépendances et des routes), vous permettant d'ajouter un package unique à votre pubspec et de commencer à travailler. Après une mise à jour Flutter, la seule chose à faire est de mettre à jour la dépendance Get et de vous mettre au travail. Get résout également les problèmes de compatibilité. Combien de fois une version d'un package n'est pas compatible avec la version d'un autre, parce que l'une utilise une dépendance dans une version et l'autre dans une autre version? Ce n'est pas non plus un problème avec Get, car tout est dans le même package et est entièrement compatible.
2- Flutter est facile, Flutter est incroyable, mais Flutter a encore quelques règles standard qui peuvent être indésirables pour la plupart des développeurs, comme `Navigator.of (context) .push (context, builder [...]`. Get simplifie le développement. Au lieu de écrire 8 lignes de code pour simplement appeler une route, vous pouvez simplement le faire: `Get.to (Home ())` et vous avez terminé, vous passerez à la page suivante. Les URL Web dynamiques sont une chose vraiment pénible à voir avec Flutter actuellement, et cela avec GetX est stupidement simple. La gestion des états dans Flutter et la gestion des dépendances sont également quelque chose qui génère beaucoup de discussions, car il y a des centaines de modèles dans la pub. Mais rien n'est aussi simple que d'ajouter un ".obs" à la fin de votre variable, et placez votre widget dans un Obx, et c'est tout, toutes les mises à jour de cette variable seront automatiquement mises à jour à l'écran.
3- Facilité sans vous soucier des performances. Les performances de Flutter sont déjà étonnantes, mais imaginez que vous utilisez un gestionnaire d'état et un localisateur pour distribuer vos classes blocs / stores / contrôleurs / etc. Vous devrez appeler manuellement l'exclusion de cette dépendance lorsque vous n'en avez pas besoin. Mais avez-vous déjà pensé à simplement utiliser votre «contrôleur`, et quand il n'était plus utilisé par personne, il serait simplement supprimé de la mémoire? C'est ce que fait GetX. Avec SmartManagement, tout ce qui n'est pas utilisé est supprimé de la mémoire et vous ne devriez pas avoir à vous soucier d'autre chose que de la programmation. Vous serez assuré de consommer le minimum de ressources nécessaires, sans même avoir créé de logique pour cela.
4- Découplage réel. Vous avez peut-être entendu le concept "séparer la vue de la business logic". Ce n'est pas une particularité de BLoC, MVC, MVVM, et tout autre standard sur le marché a ce concept. Cependant, ce concept peut souvent être atténué dans Flutter en raison de l'utilisation de `context`.
Si vous avez besoin de contexte pour trouver un InheritedWidget, vous en avez besoin dans la vue, ou passez le `context` par paramètre. Je trouve particulièrement cette solution très moche, et pour travailler en équipe, nous serons toujours dépendants de la 'business logic' de View. Getx n'est pas orthodoxe avec l'approche standard, et même s'il n'interdit pas complètement l'utilisation de StatefulWidgets, InitState, etc., il a toujours une approche similaire qui peut être plus propre. Les contrôleurs ont des cycles de vie, et lorsque vous devez faire une requête APIREST par exemple, vous ne dépendez de rien de la vue. Vous pouvez utiliser onInit pour lancer l'appel http et lorsque les données arrivent, les variables sont remplies. Comme GetX est totalement réactif (vraiment, et fonctionne sous streams), une fois les éléments remplis, tous les widgets qui utilisent cette variable seront automatiquement mis à jour dans la vue.
Cela permet aux personnes ayant une expertise de l'interface utilisateur de travailler uniquement avec des widgets et de ne pas avoir à envoyer quoi que ce soit à la business logic autre que des événements utilisateur (comme cliquer sur un bouton), tandis que les personnes travaillant avec la business logic seront libres de créer et de tester la Business logic séparément.
# Communite
## Chaines communautaires
GetX a une communauté très active et utile. Si vous avez des questions, ou souhaitez obtenir de l'aide concernant l'utilisation de ce framework, veuillez rejoindre nos canaux communautaires, votre question sera répondue plus rapidement, et ce sera l'endroit le plus approprié. Ce référentiel est exclusif pour l'ouverture des issues Github et la demande de ressources, mais n'hésitez pas à faire partie de la communauté GetX.
| **Slack** | **Discord** | **Telegram** |
| :-------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
| [![Get sur Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx) | [![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N) | [![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g) |
## Comment contribuer
_Voulez-vous contribuer au projet? Nous serons fiers de vous mettre en avant comme l'un de nos collaborateurs. Voici quelques points sur lesquels vous pouvez contribuer et améliorer encore Get (et Flutter)._
- Aider à traduire les 'Readme's dans d'autres langues.
- Ajout de documentation au readme (beaucoup de fonctions de Get n'ont pas encore été documentées).
- Rédiger des articles ou réaliser des vidéos pour apprendre à utiliser Get (ils seront insérés dans le Readme et à l'avenir dans notre Wiki).
- Offrir des PRs pour code / tests.
- Ajouter de nouvelles fonctions.
Toute contribution est bienvenue!
## Articles et videos
- [Dynamic Themes in 3 lines using GetX™](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Tutorial by [Rod Brown](https://github.com/RodBr).
- [Complete GetX™ Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) - Route management video by Amateur Coder.
- [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) - State management video by Amateur Coder.
- [GetX™ Other Features](https://youtu.be/ttQtlX_Q0eU) - Utils, storage, bindings and other features video by Amateur Coder.
- [Firestore User with GetX | Todo App](https://www.youtube.com/watch?v=BiV0DcXgk58) - Video by Amateur Coder.
- [Firebase Auth with GetX | Todo App](https://www.youtube.com/watch?v=-H-T_BSgfOE) - Video by Amateur Coder.
- [The Flutter GetX™ Ecosystem ~ State Management](https://medium.com/flutter-community/the-flutter-getx-ecosystem-state-management-881c7235511d) - State management by [Aachman Garg](https://github.com/imaachman).
- [The Flutter GetX™ Ecosystem ~ Dependency Injection](https://medium.com/flutter-community/the-flutter-getx-ecosystem-dependency-injection-8e763d0ec6b9) - Dependency Injection by [Aachman Garg](https://github.com/imaachman).
- [GetX, the all-in-one Flutter package](https://www.youtube.com/watch?v=IYQgtu9TM74) - A brief tutorial covering State Management and Navigation by Thad Carnevalli.
- [Build a To-do List App from scratch using Flutter and GetX](https://www.youtube.com/watch?v=EcnqFasHf18) - UI + State Management + Storage video by Thad Carnevalli.
- [GetX Flutter Firebase Auth Example](https://medium.com/@jeffmcmorris/getx-flutter-firebase-auth-example-b383c1dd1de2) - Article by Jeff McMorris.
- [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter.
- [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter.
... ...
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
**Languages: English (this file), [Indonesian](README.id-ID.md), [Urdu](README.ur-PK.md), [Chinese](README.zh-cn.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md), [Russian](README.ru.md), [Polish](README.pl.md), [Korean](README.ko-kr.md).**
**Languages: English (this file), [Indonesian](README.id-ID.md), [Urdu](README.ur-PK.md), [Chinese](README.zh-cn.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md), [Russian](README.ru.md), [Polish](README.pl.md), [Korean](README.ko-kr.md), [French](README-fr.md).**
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
[![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
... ...
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
_语言: 中文, [英文](README.md), [印度尼西亚](README.id-ID.md), [乌尔都语](README.ur-PK.md), [巴西葡萄牙语](README.pt-br.md), [俄语](README.ru.md), [西班牙语](README-es.md), [波兰语](README.pl.md), [韩国语](README.ko-kr.md)._
_语言: 中文, [英文](README.md), [印度尼西亚](README.id-ID.md), [乌尔都语](README.ur-PK.md), [巴西葡萄牙语](README.pt-br.md), [俄语](README.ru.md), [西班牙语](README-es.md), [波兰语](README.pl.md), [韩国语](README.ko-kr.md), [法语](README-fr.md)._
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
... ...
# Gestion des dépendances
- [Gestion des dépendances](#Gestion-des-dépendances)
- [Instanciation des methodes](#Instanciation-des-methodes)
- [Get.put()](#getput)
- [Get.lazyPut](#getlazyput)
- [Get.putAsync](#getputasync)
- [Get.create](#getcreate)
- [Utilisation de méthodes/classes instanciées](#utilisation-de-mthodes-classes-instancies)
- [Différences entre les méthodes](#differences-entre-les-methodes)
- [Bindings](#bindings)
- [Classe Bindings](#classe-bindings)
- [BindingsBuilder](#bindingsbuilder)
- [SmartManagement](#smartmanagement)
- [Comment changer](#comment-changer)
- [SmartManagement.full](#smartmanagementfull)
- [SmartManagement.onlyBuilders](#smartmanagementonlybuilders)
- [SmartManagement.keepFactory](#smartmanagementkeepfactory)
- [Comment Bindings fonctionne sous le capot](#comment-bindings-fonctionne-sous-le-capot)
- [Notes](#notes)
Get a un gestionnaire de dépendances simple et puissant qui vous permet de récupérer la même classe que votre Bloc ou Controller avec une seule ligne de code, pas de context Provider, pas d' inheritedWidget:
```dart
Controller controller = Get.put(Controller()); // Au lieu de Controller controller = Controller();
```
Au lieu d'instancier votre classe dans la classe que vous utilisez, vous l'instanciez dans l'instance Get, qui la rendra disponible dans toute votre application.
Vous pouvez donc utiliser votre contrôleur (ou classe Bloc) normalement
- Note: Si vous utilisez le gestionnaire d'état de Get, faites plus attention à l'API [Bindings] (# bindings), qui facilitera la connexion de votre vue à votre contrôleur.
- Note²: La gestion des dépendances est découplée des autres parties du package, donc si, par exemple, votre application utilise déjà un gestionnaire d'état (n'importe lequel, peu importe), vous n'avez pas besoin de changer cela, vous pouvez utiliser ce manager d'injection de dépendance sans aucun problème.
## Instanciation des methodes
Les méthodes et leurs paramètres configurables sont:
### Get.put()
La manière la plus courante d'insérer une dépendance. Bon pour les contrôleurs de vos vues par exemple.
```dart
Get.put<SomeClass>(SomeClass());
Get.put<LoginController>(LoginController(), permanent: true);
Get.put<ListItemController>(ListItemController, tag: "un String unique");
```
Ce sont toutes les options que vous pouvez définir lorsque vous utilisez put:
```dart
Get.put<S>(
// obligatoire: la classe que vous voulez que get enregistre, comme un 'controler' ou autre
// note: "S" signifie que ca peut etre une classe de n'importe quel type
S dependency
// optionnel: c'est pour quand vous voulez plusieurs classes qui sont du même type
// puisque vous obtenez normalement une classe en utilisant Get.find<Controller>(),
// vous devez utiliser ce tag pour indiquer de quelle instance vous avez besoin
// doit être un String unique
String tag,
// optionnel: par défaut, get supprimera les instances une fois qu'elles ne seront plus utilisées (exemple,
// le contrôleur d'une vue qui est fermée), mais vous pourriez avoir besoin que l'instance
// soit conservée dans toute l'application, comme une instance de sharedPreferences ou quelque chose du genre
// donc vous utilisez ceci
// équivaut à false par défaut
bool permanent = false,
// facultatif: permet après avoir utilisé une classe abstraite dans un test, de la remplacer par une autre et de suivre le test.
// équivaut à false par défaut
bool overrideAbstract = false,
// facultatif: vous permet de créer la dépendance en utilisant la fonction au lieu de la dépendance elle-même.
// ce n'est pas couramment utilisé
InstanceBuilderCallback<S> builder,
)
```
### Get.lazyPut
Il est possible de lazyLoad une dépendance afin qu'elle ne soit instanciée que lorsqu'elle est utilisée. Très utile pour les classes qui demandent beaucoup de ressources ou si vous souhaitez instancier plusieurs classes en un seul endroit (comme dans une classe Bindings) et que vous savez que vous n'utiliserez pas cette classe à ce moment-là.
```dart
/// ApiMock ne sera appelé que lorsque quelqu'un utilise Get.find <ApiMock> pour la première fois
Get.lazyPut<ApiMock>(() => ApiMock());
Get.lazyPut<FirebaseAuth>(
() {
// ... some logic if needed
return FirebaseAuth();
},
tag: Math.random().toString(),
fenix: true
)
Get.lazyPut<Controller>(() => Controller() )
```
Ce sont toutes les options que vous pouvez définir lors de l'utilisation de lazyPut:
```dart
Get.lazyPut<S>(
// obligatoire: une méthode qui sera exécutée lorsque votre classe sera appelée pour la première fois
InstanceBuilderCallback builder,
// facultatif: identique à Get.put(), il est utilisé lorsque vous voulez plusieurs instances différentes d'une même classe
// doit être unique
String tag,
// facultatif: cela est similaire à "permanent", la différence est que l'instance est supprimée lorsqu'elle
// n'est pas utilisée, mais lorsqu'elle est à nouveau nécessaire, Get recrée l'instance
// identique à "SmartManagement.keepFactory" dans l'API Bindings
// vaut false par défaut
bool fenix = false
)
```
### Get.putAsync
Si vous souhaitez enregistrer une instance async, vous pouvez utiliser `Get.putAsync`:
```dart
Get.putAsync<SharedPreferences>(() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('counter', 12345);
return prefs;
});
Get.putAsync<YourAsyncClass>(() async => await YourAsyncClass())
```
Ce sont toutes les options que vous pouvez définir lors de l'utilisation de putAsync:
```dart
Get.putAsync<S>(
// obligatoire: une méthode async qui sera exécutée pour instancier votre classe
AsyncInstanceBuilderCallback<S> builder,
// facultatif: identique à Get.put(), il est utilisé lorsque vous voulez plusieurs instances différentes d'une même classe
// doit être unique
String tag,
// facultatif: identique à Get.put(), utilisé lorsque vous devez maintenir cette instance active dans l'ensemble de l'application
// vaut false par défaut
bool permanent = false
)
```
### Get.create
Celui-ci est délicat. Une explication détaillée de ce que c'est et des différences d'avec les autres peut être trouvée dans la section [Différences entre les méthodes:](#differences-entre-les-methodes).
```dart
Get.Create<SomeClass>(() => SomeClass());
Get.Create<LoginController>(() => LoginController());
```
Ce sont toutes les options que vous pouvez définir lors de l'utilisation de create:
```dart
Get.create<S>(
// requis: une fonction qui renvoie une classe qui sera "fabriquée" chaque
// fois que `Get.find()` est appelé
// Exemple: Get.create<YourClass>(() => YourClass())
FcBuilderFunc<S> builder,
// facultatif: comme Get.put(), mais il est utilisé lorsque vous avez besoin de plusieurs instances
// d'une même classe
// Utile dans le cas où vous avez une liste oú chaque élément a besoin de son propre contrôleur
// doit être une String unique. Changez simplement de 'tag' en 'name'
String name,
// optionnel: tout comme dans `Get.put()`, c'est pour quand vous devez garder l'
// instance vivante dans toute l'application. La différence est que dans Get.create,
// permanent est 'true' par défaut
bool permanent = true
```
## Utilisation de méthodes/classes instanciées
Imaginez que vous ayez parcouru de nombreuses routes et que vous ayez besoin d'une donnée qui a été laissée dans votre contrôleur, vous auriez besoin d'un gestionnaire d'état combiné avec le 'Provider' ou Get_it, n'est-ce pas? Pas avec Get. Il vous suffit de demander à Get de "find" (trouver) votre contrôleur, vous n'avez pas besoin de dépendances supplémentaires:
```dart
final controller = Get.find<Controller>();
// OR
Controller controller = Get.find();
// Oui, cela ressemble à Magic, Get trouvera votre contrôleur et vous le livrera.
// Vous pouvez avoir 1 million de contrôleurs instanciés, Get vous trouvera toujours le bon contrôleur.
```
Et puis vous pourrez récupérer les données de votre contrôleur qui ont été obtenues là-bas:
```dart
Text(controller.textFromApi);
```
La valeur renvoyée étant une classe normale, vous pouvez faire tout ce que vous voulez:
```dart
int count = Get.find<SharedPreferences>().getInt('counter');
print(count); // donne: 12345
```
Pour supprimer une instance de Get:
```dart
Get.delete<Controller>(); //généralement, vous n'avez pas besoin de le faire car GetX supprime déjà les contrôleurs inutilisés-
```
## Differences entre les methodes
Commençons par le `fenix` de Get.lazyPut et le `permanent` des autres méthodes.
La différence fondamentale entre `permanent` et `fenix` réside dans la manière dont vous souhaitez stocker vos instances.
Renforcement: par défaut, GetX supprime les instances lorsqu'elles ne sont pas utilisées.
Cela signifie que: Si l'écran 1 a le contrôleur 1 et l'écran 2 a le contrôleur 2 et que vous supprimez la première route du Stack, (comme si vous utilisez `Get.off()` ou `Get.offNamed()`) le contrôleur 1 a perdu son utilisation, il sera donc effacé.
Mais si vous optez pour l'utilisation de `permanent: true`, alors le contrôleur ne sera pas perdu dans cette transition - ce qui est très utile pour les services que vous souhaitez maintenir actif dans toute l'application.
`fenix`, quant à lui, est destiné aux services que vous ne craignez pas de perdre entre les changements d'écran, mais lorsque vous avez besoin de ce service, vous vous attendez à ce qu'il soit vivant. Donc, fondamentalement, il supprimera le contrôleur / service / classe inutilisé, mais lorsque vous en aurez besoin, il "recréera à partir de ses cendres" une nouvelle instance.
Différences entre les méthodes:
- Get.put et Get.putAsync suivent le même ordre de création, à la différence que la seconde utilise une méthode asynchrone: ces deux méthodes créent et initialisent l'instance. Celle-ci est insérée directement dans la mémoire, en utilisant la méthode interne `insert` avec les paramètres` permanent: false` et `isSingleton: true` (ce paramètre isSingleton a pour seul but de dire s'il faut utiliser la dépendance sur` dependency` ou s'il doit utiliser la dépendance sur `FcBuilderFunc`). Après cela, `Get.find()` est appelé pour initialiser immédiatement les instances qui sont en mémoire.
- Get.create: Comme son nom l'indique, il "créera" votre dépendance! Similaire à `Get.put()`, il appelle également la méthode interne `insert` pour l'instanciation. Mais `permanent` devient vrai et` isSingleton` devient faux (puisque nous "créons" notre dépendance, il n'y a aucun moyen pour que ce soit une instance singleton, c'est pourquoi il est faux). Et comme il a `permanent: true`, nous avons par défaut l'avantage de ne pas le perdre entre les écrans! De plus, `Get.find()` n'est pas appelé immédiatement, il attend d'être utilisé dans l'écran pour être appelé. Il est créé de cette façon pour utiliser le paramètre `permanent`, depuis lors, il convient de noter que` Get.create() `a été créé dans le but de créer des instances non partagées, mais qui ne sont pas supprimées, comme par exemple un bouton dans un listView, pour lequel vous voulez une instance unique pour cette liste - à cause de cela, Get.create doit être utilisé avec GetWidget.
- Get.lazyPut: Comme son nom l'indique, il s'agit d'un processus 'paresseux'. L'instance est créée, mais elle n'est pas appelée pour être utilisée immédiatement, elle reste en attente d'être appelée. Contrairement aux autres méthodes, `insert` n'est pas appelé ici. Au lieu de cela, l'instance est insérée dans une autre partie de la mémoire, une partie chargée de dire si l'instance peut être recréée ou non, appelons-la "factory". Si nous voulons créer quelque chose pour être utilisé plus tard, il ne sera pas mélangé avec les choses actuellement utilisées. Et voici où la magie de `fenix` apparaît: si vous choisissez de laisser` fenix: false`, et que votre `smartManagement` n'est pas` keepFactory`, alors lors de l'utilisation de `Get.find`, l'instance changera la place dans la mémoire de la "factory" à la zone de mémoire d'instance commune. Juste après cela, par défaut, il est retiré de `la factory`. Maintenant, si vous optez pour `fenix: true`, l'instance continue d'exister dans cette partie dédiée, allant même vers la zone commune, pour être appelée à nouveau dans le futur.
## Bindings
L'une des grandes différences de ce package, peut-être, est la possibilité d'une intégration complète des routes, du gestionnaire d'état et du gestionnaire de dépendances.
Lorsqu'une route est supprimée de la pile, tous les contrôleurs, variables et instances d'objets qui lui sont associés sont supprimés de la mémoire. Si vous utilisez des streams ou timers, ils seront fermés automatiquement et vous n'aurez à vous soucier de rien de tout cela.
Dans la version 2.10, Get a complètement implémenté l'API Bindings.
Vous n'avez plus besoin d'utiliser la méthode init. Vous n'avez même pas besoin de `typer`(declaration de type) vos contrôleurs si vous ne le souhaitez pas. Vous pouvez démarrer vos contrôleurs et services à l'endroit approprié pour cela.
La classe Binding est une classe qui découplera l'injection de dépendances, en faisant du "binding" des routes entre le gestionnaire d'état et le gestionnaire de dépendances.
Cela permet à Get de savoir quel écran est affiché lorsqu'un contrôleur particulier est utilisé et de savoir où et comment s'en débarrasser.
De plus, la classe Binding vous permettra d'avoir le contrôle de la configuration de SmartManager. Vous pouvez configurer les dépendances à organiser lors de la suppression d'une route du Stack, ou lorsque le widget qui l'utilisait est disposé, ou ni l'un ni l'autre. Vous disposerez d'une gestion intelligente des dépendances qui fonctionnera pour vous, mais vous pourrez malgré tout la configurer comme vous le souhaitez.
### Classe Bindings
- Créer une classe et implémenter Bindings
```dart
class HomeBinding implements Bindings {}
```
Votre IDE vous demandera automatiquement de remplacer la méthode "dependencies", et il vous suffit de cliquer sur la lampe, de remplacer la méthode et d'insérer toutes les classes que vous allez utiliser sur cette route:
```dart
class HomeBinding implements Bindings {
@override
void dependencies() {
Get.lazyPut<HomeController>(() => HomeController());
Get.put<Service>(()=> Api());
}
}
class DetailsBinding implements Bindings {
@override
void dependencies() {
Get.lazyPut<DetailsController>(() => DetailsController());
}
}
```
Il vous suffit maintenant d'informer votre route, que vous utiliserez ce Binding pour établir la connexion entre le gestionnaire de routes, les dépendances et les états.
- En utilisant les routes nommées:
```dart
getPages: [
GetPage(
name: '/',
page: () => HomeView(),
binding: HomeBinding(),
),
GetPage(
name: '/details',
page: () => DetailsView(),
binding: DetailsBinding(),
),
];
```
- En utilisant les routes normales:
```dart
Get.to(Home(), binding: HomeBinding());
Get.to(DetailsView(), binding: DetailsBinding())
```
Là, vous n'avez plus à vous soucier de la gestion de la mémoire de votre application, Get le fera pour vous.
La classe Binding est appelée lorsqu'une route est appelée, vous pouvez créer un "initialBinding dans votre GetMaterialApp pour insérer toutes les dépendances qui seront créées.
```dart
GetMaterialApp(
initialBinding: SampleBind(),
home: Home(),
);
```
### BindingsBuilder
La manière par défaut de créer un binding est de créer une classe qui implémente Bindings.
Mais alternativement, vous pouvez utiliser le callback `BindingsBuilder` afin de pouvoir simplement utiliser une fonction pour instancier ce que vous désirez.
Exemple:
```dart
getPages: [
GetPage(
name: '/',
page: () => HomeView(),
binding: BindingsBuilder(() {
Get.lazyPut<ControllerX>(() => ControllerX());
Get.put<Service>(()=> Api());
}),
),
GetPage(
name: '/details',
page: () => DetailsView(),
binding: BindingsBuilder(() {
Get.lazyPut<DetailsController>(() => DetailsController());
}),
),
];
```
De cette façon, vous pouvez éviter de créer une classe Binding pour chaque route, ce qui est encore plus simple.
Les deux méthodes fonctionnent parfaitement bien et nous voulons que vous utilisiez ce qui correspond le mieux à vos goûts.
### SmartManagement
GetX par défaut supprime les contrôleurs inutilisés de la mémoire, même si un échec se produit et qu'un widget qui l'utilise n'est pas correctement supprimé.
C'est ce qu'on appelle le mode `full` de gestion des dépendances.
Mais si vous voulez changer la façon dont GetX contrôle la suppression des classes, vous avez la classe `SmartManagement` pour définir différents comportements.
#### Comment changer
Si vous souhaitez modifier cette configuration (dont vous n'avez généralement pas besoin), procédez comme suit:
```dart
void main () {
runApp(
GetMaterialApp(
smartManagement: SmartManagement.onlyBuilders //Ici
home: Home(),
)
)
}
```
#### SmartManagement.full
C'est celui par défaut. Supprime les classes qui ne sont pas utilisées et qui n'ont pas été définies pour être permanentes. Dans la majorité des cas, vous voudrez garder cette configuration intacte. Si vous débutez avec GetX, ne changez pas cela.
#### SmartManagement.onlyBuilders
Avec cette option, seuls les contrôleurs démarrés dans `init:` ou chargés dans un Binding avec `Get.lazyPut()` seront supprimés.
Si vous utilisez `Get.put()` ou `Get.putAsync()` ou toute autre approche, SmartManagement n'aura pas les autorisations pour exclure cette dépendance.
Avec le comportement par défaut, même les widgets instanciés avec "Get.put" seront supprimés, contrairement à SmartManagement.onlyBuilders.
#### SmartManagement.keepFactory
Tout comme SmartManagement.full, il supprimera ses dépendances lorsqu'elles ne seront plus utilisées. Cependant, il conservera leur factory, ce qui signifie qu'il recréera la dépendance si vous avez à nouveau besoin de cette instance.
### Comment Bindings fonctionne sous le capot
Bindings crée des `'factories' transitoires`, qui sont créées au moment où vous cliquez pour aller à un autre écran, et seront détruites dès que l'animation de changement d'écran se produit.
Cela arrive si vite que l'analyseur ne pourra même pas l'enregistrer.
Lorsque vous accédez à nouveau à cet écran, une nouvelle fabrique temporaire sera appelée, c'est donc préférable à l'utilisation de SmartManagement.keepFactory, mais si vous ne voulez pas créer de Bindings, ou si vous voulez garder toutes vos dépendances sur le même Binding , cela vous aidera certainement.
Les factories prennent peu de mémoire, elles ne contiennent pas d'instances, mais une fonction avec la "forme" de cette classe que vous voulez.
Cela a un très faible coût en mémoire, mais comme le but de cette bibliothèque est d'obtenir le maximum de performances possible en utilisant le minimum de ressources, Get supprime même les factories par défaut.
Utilisez celui qui vous convient le mieux.
## Notes
- N'UTILISEZ PAS SmartManagement.keepFactory si vous utilisez plusieurs Bindings. Il a été conçu pour être utilisé sans Bindings ou avec une seule Binding liée dans le fichier initialBinding de GetMaterialApp.
- L'utilisation de Bindings est complètement facultative, si vous le souhaitez, vous pouvez utiliser `Get.put()` et `Get.find()` sur les classes qui utilisent un contrôleur donné sans aucun problème.
Cependant, si vous travaillez avec des services ou toute autre abstraction, je vous recommande d'utiliser Bindings pour une meilleure organisation.
\ No newline at end of file
... ...
- [Gestion de route](#gestion-de-route)
- [Utilisation](#utilisation)
- [Navigation sans nom](#navigation-sans-nom)
- [Navigation par nom](#navigation-par-nom)
- [Envoyer des données aux routes nommées](#envoyer-des-donnes-aux-routes-nommes)
- [Liens URL dynamiques](#liens-url-dynamiques)
- [Middleware](#middleware)
- [Navigation sans context](#navigation-sans-context)
- [SnackBars](#snackbars)
- [Dialogs](#dialogs)
- [BottomSheets](#bottomsheets)
- [Nested Navigation](#nested-navigation)
# Gestion de route
C'est l'explication complète de tout ce qu'il y a à savoir sur Getx quand il s'agit de la gestion des routes.
## Utilisation
Ajoutez ceci à votre fichier pubspec.yaml:
```yaml
dependencies:
get:
```
Si vous allez utiliser des routes/snackbars/dialogs/bottomsheets sans contexte, ou utiliser les API Get de haut niveau, vous devez simplement ajouter "Get" avant votre MaterialApp, en le transformant en GetMaterialApp et en profiter!
```dart
GetMaterialApp( // Avant: MaterialApp(
home: MyHome(),
)
```
## Navigation sans nom
Pour accéder à un nouvel écran:
```dart
Get.to(NextScreen());
```
To close snackbars, dialogs, bottomsheets, or anything you would normally close with Navigator.pop(context);
Pour fermer les snackbars, dialogs, bottomsheets ou tout ce que vous fermez normalement avec Navigator.pop (context);
```dart
Get.back();
```
Pour aller à l'écran suivant et aucune option pour revenir à l'écran précédent (pour une utilisation dans SplashScreens, écrans de connexion, etc.)
```dart
Get.off(NextScreen());
```
Pour aller à l'écran suivant et annuler toutes les routes précédents (utile dans les paniers d'achat e-commerce, les sondages et les tests)
```dart
Get.offAll(NextScreen());
```
Pour naviguer vers l'écran suivant et recevoir ou mettre à jour des données dès que vous en revenez:
```dart
var data = await Get.to(Payment());
```
sur l'autre écran, envoyez les données pour l'écran précédent:
```dart
Get.back(result: 'success');
```
Et utilisez-les:
ex:
```dart
if(data == 'success') madeAnything();
```
Vous ne voulez pas apprendre notre syntaxe?
Changez simplement le Navigateur (majuscule) en navigateur (minuscule), et vous aurez toutes les fonctions de la navigation standard, sans avoir à utiliser 'context'.
Exemple:
```dart
// Navigateur Flutter par défaut
Navigator.of(context).push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return HomePage();
},
),
);
// Utilisez la syntaxe Flutter sans avoir besoin de 'context'
navigator.push(
MaterialPageRoute(
builder: (_) {
return HomePage();
},
),
);
// Syntaxe Get (c'est beaucoup mieux, mais vous avez le droit d'être en désaccord)
Get.to(HomePage());
```
## Navigation Par Nom
- Si vous préférez naviguer par namedRoutes, Get prend également en charge cela.
Pour aller à nextScreen
```dart
Get.toNamed("/NextScreen");
```
Pour naviguer et supprimer l'écran précédent du stack.
```dart
Get.offNamed("/NextScreen");
```
Pour naviguer et supprimer tous les écrans précédents du stack.
```dart
Get.offAllNamed("/NextScreen");
```
Pour définir des routes, utilisez GetMaterialApp:
```dart
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.zoom
),
],
)
);
}
```
Pour gérer la navigation vers des routes non définies (erreur 404), vous pouvez définir une page 'unknownRoute' dans GetMaterialApp.
```dart
void main() {
runApp(
GetMaterialApp(
unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
initialRoute: '/',
getPages: [
GetPage(name: '/', page: () => MyHomePage()),
GetPage(name: '/second', page: () => Second()),
],
)
);
}
```
### Envoyer des données aux routes nommées
Envoyez simplement ce que vous voulez comme arguments. Get accepte n'importe quoi ici, qu'il s'agisse d'une String, d'une Map, d'une List ou même d'une instance de classe.
```dart
Get.toNamed("/NextScreen", arguments: 'Get is the best');
```
dans votre classe ou contrôleur:
```dart
print(Get.arguments);
//montre: Get is the best
```
### Liens URL dynamiques
Get propose des URL dynamiques avancées, tout comme sur le Web. Les développeurs Web ont probablement déjà voulu cette fonctionnalité sur Flutter, et ont très probablement vu un package promettre cette fonctionnalité et fournir une syntaxe totalement différente de celle d'une URL sur le Web, mais Get résout également cela.
```dart
Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
```
sur votre classe controller/bloc/stateful/stateless:
```dart
print(Get.parameters['id']);
// donne: 354
print(Get.parameters['name']);
// donne: Enzo
```
Vous pouvez également recevoir facilement des paramètres nommés avec Get:
```dart
void main() {
runApp(
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => MyHomePage(),
),
GetPage(
name: '/profile/',
page: () => MyProfile(),
),
//Vous pouvez définir une page différente pour les routes avec arguments, et une autre sans arguments, mais pour cela vous devez utiliser la barre oblique '/' sur la route qui ne recevra pas d'arguments comme ci-dessus.
GetPage(
name: '/profile/:user',
page: () => UserProfile(),
),
GetPage(
name: '/third',
page: () => Third(),
transition: Transition.cupertino
),
],
)
);
}
```
Envoyer des données sur le nom de la route
```dart
Get.toNamed("/profile/34954");
```
Sur le deuxième écran, recevez les données par paramètre
```dart
print(Get.parameters['user']);
// donne: 34954
```
Et maintenant, tout ce que vous avez à faire est d'utiliser Get.toNamed() pour parcourir vos routes nommées, sans aucun contexte (vous pouvez appeler vos routes directement à partir de votre classe BLoC ou Controller), et lorsque votre application est compilée sur le Web, vos routes apparaîtront dans l'url <3
### Middleware
Si vous souhaitez écouter les événements Get pour déclencher des actions, vous pouvez utiliser routingCallback pour le faire:
```dart
GetMaterialApp(
routingCallback: (routing) {
if(routing.current == '/second'){
openAds();
}
}
)
```
Si vous n'utilisez pas GetMaterialApp, vous pouvez utiliser l'API manuelle pour attacher l'observateur Middleware.
```dart
void main() {
runApp(
MaterialApp(
onGenerateRoute: Router.generateRoute,
initialRoute: "/",
navigatorKey: Get.key,
navigatorObservers: [
GetObserver(MiddleWare.observer), // ICI !!!
],
),
);
}
```
Créez une classe MiddleWare
```dart
class MiddleWare {
static observer(Routing routing) {
/// Vous pouvez écouter en plus des routes, des snackbars, des dialogs et des bottomsheets sur chaque écran.
/// Si vous devez saisir l'un de ces 3 événements directement ici,
/// vous devez spécifier que l'événement est != Ce que vous essayez de faire.
if (routing.current == '/second' && !routing.isSnackbar) {
Get.snackbar("Hi", "You are on second route");
} else if (routing.current =='/third'){
print('dernière route');
}
}
}
```
Maintenant, utilisez Get sur votre code:
```dart
class First extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.add),
onPressed: () {
Get.snackbar("hi", "i am a modern snackbar");
},
),
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
Get.toNamed("/second");
},
),
),
);
}
}
class Second extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.add),
onPressed: () {
Get.snackbar("hi", "i am a modern snackbar");
},
),
title: Text('second Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
Get.toNamed("/third");
},
),
),
);
}
}
class Third extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Third Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Get.back();
},
child: Text('Go back!'),
),
),
);
}
}
```
## Navigation sans context
### SnackBars
Pour avoir un simple SnackBar avec Flutter, vous devez obtenir le 'context' de Scaffold, ou vous devez utiliser un GlobalKey attaché à votre Scaffold
```dart
final snackBar = SnackBar(
content: Text('Hi!'),
action: SnackBarAction(
label: 'I am a old and ugly snackbar :(',
onPressed: (){}
),
);
// Trouvez le scaffold dans l'arborescence des widgets et utilisez-le pour afficher un SnackBar.
Scaffold.of(context).showSnackBar(snackBar);
```
Avec Get:
```dart
Get.snackbar('Hi', 'i am a modern snackbar');
```
Avec Get, tout ce que vous avez à faire est d'appeler votre Get.snackbar à partir de n'importe où dans votre code ou de le personnaliser comme vous le souhaitez!
```dart
Get.snackbar(
"Hey i'm a Get SnackBar!", // title
"C'est incroyable! J'utilise SnackBar sans context, sans code standard, sans Scaffold, c'est quelque chose de vraiment incroyable!", // message
icon: Icon(Icons.alarm),
shouldIconPulse: true,
onTap:(){},
barBlur: 20,
isDismissible: true,
duration: Duration(seconds: 3),
);
////////// TOUTES LES FONCTIONNALITÉS //////////
// Color colorText,
// Duration duration,
// SnackPosition snackPosition,
// Widget titleText,
// Widget messageText,
// bool instantInit,
// Widget icon,
// bool shouldIconPulse,
// double maxWidth,
// EdgeInsets margin,
// EdgeInsets padding,
// double borderRadius,
// Color borderColor,
// double borderWidth,
// Color backgroundColor,
// Color leftBarIndicatorColor,
// List<BoxShadow> boxShadows,
// Gradient backgroundGradient,
// FlatButton mainButton,
// OnTap onTap,
// bool isDismissible,
// bool showProgressIndicator,
// AnimationController progressIndicatorController,
// Color progressIndicatorBackgroundColor,
// Animation<Color> progressIndicatorValueColor,
// SnackStyle snackStyle,
// Curve forwardAnimationCurve,
// Curve reverseAnimationCurve,
// Duration animationDuration,
// double barBlur,
// double overlayBlur,
// Color overlayColor,
// Form userInputForm
///////////////////////////////////
```
Si vous préférez le snack-bar traditionnel, ou souhaitez le personnaliser à partir de zéro, y compris en ajoutant une seule ligne (Get.snackbar utilise un titre et un message obligatoires), vous pouvez utiliser
`Get.rawSnackbar ();` qui fournit l'API brute sur laquelle Get.snackbar a été construit.
### Dialogs
Pour ouvrir un 'dialog':
```dart
Get.dialog(VotreDialogWidget());
```
Pour ouvrir le 'dialog' par défaut:
```dart
Get.defaultDialog(
onConfirm: () => print("Ok"),
middleText: "Dialog made in 3 lines of code"
);
```
Vous pouvez également utiliser Get.generalDialog au lieu de showGeneralDialog.
Pour tous les autres widgets de la boîte de dialogue Flutter, y compris cupertinos, vous pouvez utiliser Get.overlayContext au lieu du context et l'ouvrir n'importe où dans votre code.
Pour les widgets qui n'utilisent pas Overlay, vous pouvez utiliser Get.context.
Ces deux contextes fonctionneront dans 99% des cas pour remplacer le context de votre interface utilisateur, sauf dans les cas où inheritedWidget est utilisé sans context de navigation.
### BottomSheets
Get.bottomSheet est comme showModalBottomSheet, mais n'a pas besoin de 'context'.
```dart
Get.bottomSheet(
Container(
child: Wrap(
children: <Widget>[
ListTile(
leading: Icon(Icons.music_note),
title: Text('Music'),
onTap: () {}
),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video'),
onTap: () {},
),
],
),
)
);
```
## Nested Navigation
Getx a rendu la navigation imbriquée de Flutter encore plus facile.
Vous n'avez pas besoin de 'context' et vous trouverez votre stack de navigation par ID.
- NOTE: La création de stacks de navigation parallèles peut être dangereuse. L'idéal est de ne pas utiliser NestedNavigators, ou de l'utiliser avec parcimonie. Si votre projet l'exige, allez-y, mais gardez à l'esprit que conserver plusieurs stacks de navigation en mémoire n'est peut-être pas une bonne idée pour la consommation de RAM.
Voyez comme c'est simple:
```dart
Navigator(
key: Get.nestedKey(1), // créez une clé par index
initialRoute: '/',
onGenerateRoute: (settings) {
if (settings.name == '/') {
return GetPageRoute(
page: () => Scaffold(
appBar: AppBar(
title: Text("Main"),
),
body: Center(
child: FlatButton(
color: Colors.blue,
onPressed: () {
Get.toNamed('/second', id:1); // naviguer votre itinéraire imbriqué par index
},
child: Text("Go to second"),
),
),
),
);
} else if (settings.name == '/second') {
return GetPageRoute(
page: () => Center(
child: Scaffold(
appBar: AppBar(
title: Text("Main"),
),
body: Center(
child: Text("second")
),
),
),
);
}
}
),
```
... ...
- [Gestion d'État](#gestion-d-etat)
- [Gestionnaire d'état réactif](#gestionnaire-d-etat-reactif)
- [Avantages](#avantages)
- [Performance maximale:](#performance-maximale)
- [Déclaration d'une variable réactive](#declaration-d-une-variable-reactive)
- [Avoir un état réactif, c'est facile.](#avoir-un-etat-reactif-c-est-facile)
- [Utilisation des valeurs dans la Vue](#utilisation-des-valeurs-dans-la-vue)
- [Conditions pour reconstruire](#conditions-pour-reconstruire)
- [Quand utiliser .obs](#quand-utiliser-obs)
- [Remarque sur List](#remarque-sur-list)
- [Pourquoi je dois utiliser .value](#pourquoi-je-dois-utiliser-value)
- [Obx()](#obx)
- [Workers](#workers)
- [Gestionnaire d'état simple](#gestionnaire-d-etat-simple)
- [Atouts](#atouts)
- [Utilisation](#utilisation)
- [Comment il gère les contrôleurs](#comment-il-gre-les-contrleurs)
- [Vous n'aurez plus besoin de StatefulWidgets](#vous-naurez-plus-besoin-de-statefulwidgets)
- [Pourquoi ça existe](#pourquoi-ca-existe)
- [Autres façons de l'utiliser](#autres-formes-d-utilisation)
- [IDs Uniques](#ids-uniques)
- [Mélanger les deux gestionnaires d'état](#mixing-the-two-state-managers)
- [GetBuilder vs GetX vs Obx vs MixinBuilder](#getbuilder-vs-getx-vs-obx-vs-mixinbuilder)
# Gestion d Etat
GetX n'utilise pas Streams ou ChangeNotifier comme les autres gestionnaires d'état. Pourquoi? En plus de créer des applications pour Android, iOS, Web, Linux, MacOS et Linux, GetX vous permet de créer des applications serveur avec la même syntaxe que Flutter / GetX. Afin d'améliorer le temps de réponse et de réduire la consommation de RAM, nous avons créé GetValue et GetStream, des solutions à faible latence qui offrent beaucoup de performances, à un faible coût d'exploitation. Nous utilisons cette base pour construire toutes nos ressources, y compris la gestion d'état.
- _Complexité_: Certains gestionnaires d'État sont complexes et ont beaucoup de code standard. Avec GetX, vous n'avez pas à définir une classe pour chaque événement, le code est très propre et clair, et vous faites beaucoup plus en écrivant moins. Beaucoup de gens ont abandonné Flutter à cause de ce sujet, et ils ont enfin une solution stupidement simple pour gérer les états.
- _Aucun générateur de code_: Vous passez la moitié de votre temps de développement à écrire la logique de votre application. Certains gestionnaires d'état s'appuient sur des générateurs de code pour avoir un code lisible minimal. Changer une variable et avoir à exécuter build_runner peut être improductif, et souvent le temps d'attente après un redémarrage sera long, et vous devrez boire beaucoup de café.
Avec GetX, tout est réactif, et rien ne dépend des générateurs de code, augmentant votre productivité dans tous les aspects de votre développement.
- _Cela ne dépend pas de 'context'_: Vous avez probablement déjà eu besoin d'envoyer le contexte de votre vue à un contrôleur, ce qui rend le couplage de la vue avec votre logique métier élevé. Vous avez probablement dû utiliser une dépendance dans un endroit qui n'a pas de contexte, et avez dû passer le contexte à travers différentes classes et fonctions. Cela n'existe tout simplement pas avec GetX. Vous avez accès à vos contrôleurs depuis vos contrôleurs sans aucun contexte. Vous n'avez pas besoin d'envoyer le contexte par paramètre pour rien.
- _Contrôle granulaire_: la plupart des gestionnaires d'état sont basés sur ChangeNotifier. ChangeNotifier notifiera tous les widgets qui en dépendent lors de l'appel de notifyListeners. Si vous avez 40 widgets sur un écran, qui ont une variable de votre classe ChangeNotifier, lorsque vous en mettez un à jour, tous seront reconstruits.
Avec GetX, même les widgets imbriqués sont respectés. Si Obx gère votre ListView et un autre gère une case à cocher dans ListView, lors de la modification de la valeur CheckBox, il ne sera mis à jour que, lors de la modification de la valeur List, seul le ListView sera mis à jour.
- _Il ne reconstruit que si sa variable change VRAIMENT_: GetX a un contrôle de flux, cela signifie que si vous affichez un texte avec 'Paola', si vous changez à nouveau la variable observable en 'Paola', le widget ne sera pas reconstruit. C'est parce que GetX sait que `Paola` est déjà affiché dans Text et ne fera pas de reconstructions inutiles.
La plupart (sinon tous) les gestionnaires d'état actuels se reconstruiront à l'écran.
## Gestionnaire d etat reactif
La programmation réactive peut aliéner de nombreuses personnes car on dit qu'elle est compliquée. GetX transforme la programmation réactive en quelque chose d'assez simple:
- Vous n'aurez pas besoin de créer des StreamControllers.
- Vous n'aurez pas besoin de créer un StreamBuilder pour chaque variable
- Vous n'aurez pas besoin de créer une classe pour chaque état.
- Vous n'aurez pas besoin de créer un 'get' pour une valeur initiale.
La programmation réactive avec Get est aussi simple que d'utiliser setState.
Imaginons que vous ayez une variable de 'name' et que vous souhaitiez que chaque fois que vous la modifiez, tous les widgets qui l'utilisent soient automatiquement modifiés.
Voici votre variable:
```dart
var name = 'Jonatas Borges';
```
Pour la rendre observable, il vous suffit d'ajouter ".obs" à la fin:
```dart
var name = 'Jonatas Borges'.obs;
```
C'est *tout*. Si simple que ca.
A partir de maintenant, nous pourrions désigner ces variables réactives - ". Obs" (ervables) comme _Rx_.
Qu'est ce qui s'est passé derrière les rideaux? Nous avons créé un `Stream` de` String`s, assigné la valeur initiale `" Jonatas Borges "`, nous avons notifié tous les widgets qui utilisent `" Jonatas Borges "` qu'ils "appartiennent" maintenant à cette variable, et quand la valeur _Rx_ changements, ils devront également changer.
C'est la **magie de GetX**, grâce aux performances de Dart.
Mais, comme nous le savons, un `Widget` ne peut être changé que s'il est à l'intérieur d'une fonction, car les classes statiques n'ont pas le pouvoir de" changer automatiquement ".
Vous devrez créer un `StreamBuilder`, vous abonner à cette variable pour écouter les changements et créer une" cascade "de` StreamBuilder` imbriqués si vous voulez changer plusieurs variables dans la même portée, non?
Non, vous n'avez pas besoin d'un `StreamBuilder`, mais vous avez raison pour les classes statiques.
Eh bien, dans la vue, nous avons généralement beaucoup de code standard lorsque nous voulons changer un widget spécifique, c'est la manière Flutter.
Avec **GetX**, vous pouvez également oublier ce code passe-partout.
`StreamBuilder( … )`? `initialValue: …`? `builder: …`? Non, il vous suffit de placer cette variable dans un widget `Obx()`.
```dart
Obx (() => Text (controller.name));
```
_Que devez-vous mémoriser?_ Seulement `Obx(() =>`.
Vous passez simplement ce Widget via une fonction dans un `Obx()` (l' "Observateur" du _Rx_).
`Obx` est assez intelligent et ne changera que si la valeur de` controller.name` change.
Si `name` est` "John" `, et que vous le changez en` "John" `(` name.value = "John" `), comme c'est la même` valeur` qu'avant, rien ne changera à l'écran, et `Obx`, pour économiser les ressources, ignorera simplement la nouvelle valeur et ne reconstruira pas le widget. **N'est-ce pas incroyable?**
> Alors, que faire si j'ai 5 variables _Rx_ (observables) dans un `Obx`?
Il sera simplement mis à jour lorsque **l'un d'entre eux** change.
> Et si j'ai 30 variables dans une classe, lorsque j'en mets une à jour, est-ce que cela va mettre à jour **toutes** les variables qui sont dans cette classe?
Non, juste le **Widget spécifique** qui utilise cette variable _Rx_.
Ainsi, **GetX** ne met à jour l'écran que lorsque la variable _Rx_ change sa valeur.
```
final isOpen = false.obs;
// Rien de ne change... valeur identique.
void onButtonTap() => isOpen.value=false;
```
### Avantages
**GetX()** vous aide lorsque vous avez besoin d'un contrôle **granulaire** sur ce qui est mis à jour.
Si vous n'avez pas besoin d'ID uniques, car toutes vos variables seront modifiées lorsque vous effectuez une action, utilisez `GetBuilder`,
parce que c'est un Simple State Updater (en blocs, comme `setState()`), fait en seulement quelques lignes de code.
Il a été rendu simple, pour avoir le moins d'impact sur le processeur, et juste pour remplir un seul objectif (une reconstruction de _l'état_) et dépenser le minimum de ressources possible.
Si vous avez besoin d'un State Manager **puissant** , vous ne pouvez pas vous tromper avec **GetX**.
Cela ne fonctionne pas avec les variables, mais __flows__, tout ce qu'il contient sont des `Streams` en réalité.
Vous pouvez utiliser _rxDart_ en conjonction avec lui, car tout est `Streams`.
Vous pouvez écouter les changements de chaque "variable _Rx_",
parce que tout ce qui se trouve dedans est un `Streams`.
C'est littéralement une approche _BLoC_, plus facile que _MobX_, et sans générateurs de code ni décorations.
Vous pouvez transformer **n'importe quoi** en un _"Observable"_ avec juste un `.obs`.
### Performance maximale:
En plus d'avoir un algorithme intelligent pour des reconstructions minimales, **GetX** utilise des comparateurs
pour s'assurer que l'État a changé.
Si vous rencontrez des erreurs dans votre application et envoyez un changement d'état en double,
**GetX** garantira qu'il ne plantera pas.
Avec **GetX**, l'état ne change que si la `valeur` change.
C'est la principale différence entre **GetX** et l'utilisation de _`computed` de MobX_.
Lors de la jonction de deux __observables__, si l'une change; le listener de cet _observable_ changera également.
Avec **GetX**, si vous joignez deux variables, `GetX()` (similaire à `Observer()`), ne se reconstruira que si cela implique un réel changement d'état.
### Declaration d une variable reactive
Vous avez 3 façons de transformer une variable en "observable".
1 - La première est d'utiliser **`Rx{Type}`**.
```dart
// la valeur initiale est recommandée, mais pas obligatoire
final name = RxString('');
final isLogged = RxBool(false);
final count = RxInt(0);
final balance = RxDouble(0.0);
final items = RxList<String>([]);
final myMap = RxMap<String, int>({});
```
2 - La seconde consiste à utiliser **`Rx`** et à utiliser les types `Rx<Type>` Génériques Darts
```dart
final name = Rx<String>('');
final isLogged = Rx<Bool>(false);
final count = Rx<Int>(0);
final balance = Rx<Double>(0.0);
final number = Rx<Num>(0);
final items = Rx<List<String>>([]);
final myMap = Rx<Map<String, int>>({});
// Classes personnalisées - il peut s'agir de n'importe quelle classe, littéralement
final user = Rx<User>();
```
3 - La troisième approche, plus pratique, plus facile et préférée, ajoutez simplement **`.obs`** comme propriété de votre` valeur`:
```dart
final name = ''.obs;
final isLogged = false.obs;
final count = 0.obs;
final balance = 0.0.obs;
final number = 0.obs;
final items = <String>[].obs;
final myMap = <String, int>{}.obs;
// Classes personnalisées - il peut s'agir de n'importe quelle classe, littéralement
final user = User().obs;
```
##### Avoir un etat reactif, c est facile.
Comme nous le savons, _Dart_ se dirige maintenant vers _null safety_.
Pour être prêt, à partir de maintenant, vous devez toujours commencer vos variables _Rx_ avec une **valeur initiale**.
> Transformer une variable en _observable_ + _valeurInitiale_ avec **GetX** est l'approche la plus simple et la plus pratique.
Vous allez littéralement ajouter un "".obs"" à la fin de votre variable, et **c'est tout**, vous l'avez rendue observable,
et sa `.value`, eh bien, sera la _valeurInitiale_.
### Utilisation des valeurs dans la Vue
```dart
// dans le controlleur
final count1 = 0.obs;
final count2 = 0.obs;
int get sum => count1.value + count2.value;
```
```dart
// dans la vue
GetX<Controller>(
builder: (controller) {
print("count 1 reconstruction");
return Text('${controller.count1.value}');
},
),
GetX<Controller>(
builder: (controller) {
print("count 2 reconstruction");
return Text('${controller.count2.value}');
},
),
GetX<Controller>(
builder: (controller) {
print("count 3 reconstruction");
return Text('${controller.sum}');
},
),
```
Si nous incrémentons `count1.value++`, cela affichera:
- `count 1 reconstruction`
- `count 3 reconstruction`
parce que `count1` a une valeur de `1`, et `1 + 0 = 1`, changeant la valeur du getter `sum`.
Si nous incrémentons `count2.value++`, cela affichera:
- `count 2 reconstruction`
- `count 3 reconstruction`
parce que `count2.value` a changé et que le résultat de `sum` est maintenant `2`.
- NOTE: Par défaut, le tout premier événement reconstruira le widget, même s'il s'agit de la même `valeur`.
Ce comportement existe en raison de variables booléennes.
Imaginez que vous fassiez ceci:
```dart
var isLogged = false.obs;
```
Et puis, vous vérifiez si un utilisateur est "connecté" pour déclencher un événement dans `ever`.
```dart
@override
onInit(){
ever(isLogged, fireRoute);
isLogged.value = await Preferences.hasToken();
}
fireRoute(logged) {
if (logged) {
Get.off(Home());
} else {
Get.off(Login());
}
}
```
si `hasToken` était `false`, il n'y aurait pas de changement à `isLogged`, donc` ever() `ne serait jamais appelé.
Pour éviter ce type de comportement, la première modification d'un _observable_ déclenchera toujours un événement,
même s'il contient la même `.value`.
Vous pouvez supprimer ce comportement si vous le souhaitez, en utilisant:
`isLogged.firstRebuild = false;`
### Conditions pour reconstruire
En outre, Get fournit un contrôle d'état raffiné. Vous pouvez conditionner un événement (comme l'ajout d'un objet à une liste), à ​​une certaine condition.
```dart
// Premier paramètre: condition, doit retourner vrai ou faux.
// Deuxième paramètre: la nouvelle valeur à appliquer si la condition est vraie.
list.addIf(item < limit, item);
```
Sans décorations, sans générateur de code, sans complications :smile:
Connaissez-vous l'application 'counter' de Flutter? Votre classe Controller pourrait ressembler à ceci:
```dart
class CountController extends GetxController {
final count = 0.obs;
}
```
Avec un simple:
```dart
controller.count.value++
```
Vous pouvez mettre à jour la variable de compteur dans votre interface utilisateur, quel que soit l'endroit où elle est stockée.
### Quand utiliser .obs
Vous pouvez tout transformer sur obs. Voici deux façons de procéder:
* Vous pouvez convertir vos valeurs de classe en obs
```dart
class RxUser {
final name = "Camila".obs;
final age = 18.obs;
}
```
* ou vous pouvez convertir la classe entière en un observable:
```dart
class User {
User({String name, int age});
var name;
var age;
}
// en instanciant:
final user = User(name: "Camila", age: 18).obs;
```
### Remarque sur List
Les listes sont complètement observables, tout comme les objets qu'elles contiennent. De cette façon, si vous ajoutez une valeur à une liste, cela reconstruira automatiquement les widgets qui l'utilisent.
Vous n'avez pas non plus besoin d'utiliser ".value" avec des listes, l'incroyable api de Dart nous a permis de supprimer cela.
Malheureusement, les types primitifs comme String et int ne peuvent pas être étendus, ce qui rend l'utilisation de .value obligatoire, mais ce ne sera pas un problème si vous travaillez avec des getters et des setters pour ceux-ci.
```dart
// Dans le controlleur
final String title = 'User Info:'.obs;
final list = List<User>().obs;
// Dans la vue
Text(controller.title.value), // La String doit avoir .value devant elle
ListView.builder (
itemCount: controller.list.length // pas besoin pour List
)
```
Lorsque vous rendez vos propres classes observables, il existe une manière différente de les mettre à jour:
```dart
// sur le fichier modèle
// nous allons rendre la classe entière observable au lieu de chaque attribut
class User() {
User({this.name = '', this.age = 0});
String name;
int age;
}
// Dans le controlleur
final user = User().obs;
// lorsque vous devez mettre à jour la variable utilisateur:
user.update( (user) { // ce paramètre est la classe même que vous souhaitez mettre à jour
user.name = 'Jonny';
user.age = 18;
});
// une autre manière de mettre à jour la variable user:
user(User(name: 'João', age: 35));
// Dans la vue:
Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
// vous pouvez également accéder aux valeurs du modèle sans le .value:
user().name; //notez que c'est la variable utilisateur, pas la classe (la variable a un u minuscule)
```
Vous n'êtes pas obligé de travailler avec des setters si vous ne le souhaitez pas. vous pouvez utiliser les API `assign` et `assignAll`.
L'API `assign` effacera votre liste et ajoutera un seul objet que vous souhaitez.
L'API `assignAll` effacera la liste existante et ajoutera tous les objets itérables que vous y injecterez.
### Pourquoi je dois utiliser .value
Nous pourrions supprimer l'obligation d'utiliser 'value' pour `String` et` int` avec une simple décoration et un générateur de code, mais le but de cette bibliothèque est précisément d'éviter les dépendances externes. Nous souhaitons proposer un environnement prêt à la programmation, impliquant l'essentiel (gestion des routes, des dépendances et des états), de manière simple, légère et performante, sans avoir besoin d'un package externe.
Vous pouvez littéralement ajouter 3 lettres à votre pubspec (get) et un signe deux-points et commencer la programmation. Toutes les solutions incluses par défaut, de la gestion des routes à la gestion des états, visent la facilité, la productivité et la performance.
Le poids total de cette bibliothèque est inférieur à celui d'un seul gestionnaire d'état, bien qu'il s'agisse d'une solution complète, et c'est ce que vous devez comprendre.
Si vous êtes dérangé par `.value`, et comme un générateur de code, MobX est une excellente alternative, et vous pouvez l'utiliser en conjonction avec Get. Pour ceux qui veulent ajouter une seule dépendance dans pubspec et commencer à programmer sans se soucier de l'incompatibilité de la version d'un package avec un autre, ou si l'erreur d'une mise à jour d'état vient du gestionnaire d'état ou de la dépendance, ou encore, ne veulent pas s'inquiéter de la disponibilité des contrôleurs, que ce soit littéralement "juste de la programmation", get est tout simplement parfait.
Si vous n'avez aucun problème avec le générateur de code MobX, ou si vous n'avez aucun problème avec le code standard BLoC, vous pouvez simplement utiliser Get pour les routes et oublier qu'il a un gestionnaire d'état. Get SEM et RSM sont nés par nécessité, mon entreprise avait un projet avec plus de 90 contrôleurs, et le générateur de code a simplement pris plus de 30 minutes pour terminer ses tâches après un Flutter Clean sur une machine raisonnablement bonne, si votre projet il a 5, 10, 15 contrôleurs, n'importe quel gestionnaire d'état vous suffira bien. Si vous avez un projet d'une taille absurde et que le générateur de code est un problème pour vous, cette solution vous a été attribuée.
Évidemment, si quelqu'un veut contribuer au projet et créer un générateur de code, ou quelque chose de similaire, je vais créer un lien dans ce readme comme alternative, mon besoin n'est pas le besoin de tous les développeurs, mais pour l'instant je dis q'il y a de bonnes solutions qui font déjà cela, comme MobX.
### Obx()
Les types dans Get à l'aide de Bindings ne sont pas nécessaires. Vous pouvez utiliser le widget Obx, au lieu de GetX, qui ne reçoit que la fonction anonyme qui crée un widget.
Évidemment, si vous n'utilisez pas de type, vous devrez avoir une instance de votre contrôleur pour utiliser les variables, ou utiliser `Get.find<Controller>()` .value ou Controller.to.value pour récupérer la valeur .
### Workers
Les 'workers' vous assisteront, déclenchant des callbacks spécifiques lorsqu'un événement se produit.
```dart
/// Appelée à chaque fois que `count1` change.
ever(count1, (_) => print("$_ a été modifié"));
/// Appelée uniquement la première fois que la variable est modifiée
once(count1, (_) => print("$_ a été changé une fois"));
/// Anti DDos - Appelée chaque fois que l'utilisateur arrête de taper pendant 1 seconde, par exemple.
debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
/// Ignore toutes les modifications pendant 1 seconde.
interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
```
Tous les workers (sauf `debounce`) ont un paramètre nommé `condition`, qui peut etre un `bool` ou un callback qui retourne un `bool`.
Cette `condition` definit quand la fonction `callback` est executée.
Tous les workers renvoyent un objet `Worker`, qui peut être utilisé pour annuler ( via `dispose()` ) le `worker`.
- **`ever`**
est appelée chaque fois que la variable _Rx_ émet une nouvelle valeur.
- **`everAll`**
Un peu comme `ever`, mais il prend une` List` de valeurs _Rx_. Appelée chaque fois que sa variable est changée. C'est tout.
- **`once`**
'once' est appelée uniquement la première fois que la variable a été modifiée.
- **`debounce`**
'debounce' est très utile dans les fonctions de recherche, où vous souhaitez que l'API ne soit appelée que lorsque l'utilisateur a fini de taper. Si l'utilisateur tape "Jonny", vous aurez 5 recherches dans les API, par la lettre J, o, n, n et y. Avec Get, cela ne se produit pas, car vous aurez un Worker "anti-rebond" qui ne sera déclenché qu'à la fin de la saisie.
- **`interval`**
'interval' est différent de 'debounce'. Avec `debounce` si l'utilisateur fait 1000 changements à une variable en 1 seconde, il n'enverra que le dernier après le temporisateur stipulé (la valeur par défaut est 800 millisecondes). 'Interval' ignorera à la place toutes les actions de l'utilisateur pour la période stipulée. Si vous envoyez des événements pendant 1 minute, 1000 par seconde, debounce ne vous enverra que le dernier, lorsque l'utilisateur arrête de mitrailler les événements. interval délivrera des événements toutes les secondes, et s'il est réglé sur 3 secondes, il fournira 20 événements cette minute. Ceci est recommandé pour éviter les abus, dans des fonctions où l'utilisateur peut rapidement cliquer sur quelque chose et obtenir un avantage (imaginez que l'utilisateur puisse gagner des pièces en cliquant sur quelque chose, s'il cliquait 300 fois dans la même minute, il aurait 300 pièces, en utilisant l'intervalle, vous pouvez définir une période de 3 secondes, et même en cliquant 300 ou mille fois, le maximum qu'il obtiendrait en 1 minute serait de 20 pièces, en cliquant 300 ou 1 million de fois). Le 'debounce' convient aux anti-DDos, pour des fonctions comme la recherche où chaque changement de onChange entraînerait une requête à votre api. Debounce attendra que l'utilisateur arrête de taper le nom, pour faire la demande. S'il était utilisé dans le scénario de pièces mentionné ci-dessus, l'utilisateur ne gagnerait qu'une pièce, car il n'est exécuté que lorsque l'utilisateur "fait une pause" pendant le temps établi.
- NOTE: Les 'workers' doivent toujours être utilisés lors du démarrage d'un contrôleur ou d'une classe, il doit donc toujours être dans onInit (recommandé), le constructeur de classe ou l'initState d'un StatefulWidget (cette pratique n'est pas recommandée dans la plupart des cas, mais cela ne devrait poser aucun problème).
## Gestionnaire d etat simple
Get a un gestionnaire d'état extrêmement léger et facile, qui n'utilise pas ChangeNotifier, répondra aux besoins en particulier des nouveaux utilisateurs de Flutter et ne posera pas de problèmes pour les applications volumineuses.
GetBuilder vise précisément le contrôle de plusieurs états. Imaginez que vous avez ajouté 30 produits à un panier, que vous cliquez sur supprimer un, en même temps que la liste est mise à jour, le prix est mis à jour et le badge dans le panier est mis à jour avec un nombre plus petit. Ce type d'approche fait de GetBuilder un tueur, car il regroupe les états et les modifie tous à la fois sans aucune "logique de calcul" pour cela. GetBuilder a été créé avec ce type de situation à l'esprit, car pour un changement d'état éphémère, vous pouvez utiliser setState et vous n'aurez pas besoin d'un gestionnaire d'état pour cela.
De cette façon, si vous voulez un contrôleur individuel, vous pouvez lui attribuer des ID ou utiliser GetX. Cela dépend de vous, en vous rappelant que plus vous avez de widgets "individuels", plus les performances de GetX se démarqueront, tandis que les performances de GetBuilder devraient être supérieures, en cas de changement d'état multiple.
### Atouts
1. Met à jour uniquement les widgets requis.
2. N'utilise pas changeNotifier, c'est le gestionnaire d'état qui utilise le moins de mémoire (proche de 0 Mo).
3. Oubliez StatefulWidget! Avec Get, vous n'en aurez jamais besoin. Avec les autres gestionnaires d'états, vous devrez probablement utiliser un StatefulWidget pour obtenir l'instance de votre fournisseur, BLoC, MobX Controller, etc. Mais vous êtes-vous déjà arrêté pour penser que votre appBar, votre 'scaffold', et la plupart des les widgets de votre classe sont sans état (stateless)? Alors pourquoi sauvegarder l'état d'une classe entière, si vous pouvez sauvegarder l'état du widget qui est `avec état` (statefull)? Get résout cela aussi. Créez une classe sans état, rendez tout `sans état`. Si vous devez mettre à jour un seul composant, enveloppez-le avec GetBuilder et son état sera conservé.
4. Organisez votre projet pour de vrai! Les contrôleurs ne doivent pas être dans votre interface utilisateur, placer votre TextEditController ou tout contrôleur que vous utilisez dans votre classe Controller.
5. Avez-vous besoin de déclencher un événement pour mettre à jour un widget dès son rendu? GetBuilder a la propriété "initState", tout comme StatefulWidget, et vous pouvez appeler des événements depuis votre contrôleur, directement depuis celui-ci, aucun événement n'étant placé dans votre initState.
6. Avez-vous besoin de déclencher une action comme la fermeture de stream, de timers, etc.? GetBuilder a également la propriété dispose(), où vous pouvez appeler des événements dès que ce widget est détruit.
7. N'utilisez les streams que si nécessaire. Vous pouvez utiliser vos StreamControllers à l'intérieur de votre contrôleur normalement, et utiliser StreamBuilder également normalement, mais rappelez-vous qu'un stream consomme raisonnablement de la mémoire, la programmation réactive est belle, mais vous ne devriez pas en abuser. 30 streams ouverts simultanément peuvent être pires que changeNotifier (et changeNotifier est très mauvais).
8. Mettez à jour les widgets sans dépenser de RAM pour cela. Get stocke uniquement l'ID de créateur GetBuilder et met à jour ce GetBuilder si nécessaire. La consommation de mémoire du stockage get ID en mémoire est très faible, même pour des milliers de GetBuilders. Lorsque vous créez un nouveau GetBuilder, vous partagez en fait l'état de GetBuilder qui a un ID de créateur. Un nouvel état n'est pas créé pour chaque GetBuilder, ce qui économise BEAUCOUP de RAM pour les applications volumineuses. Fondamentalement, votre application sera entièrement sans état (stateless), et les quelques widgets qui seront stateful (dans GetBuilder) auront un seul état, et par conséquent, la mise à jour d'un seul les mettra tous à jour. L'état est unique.
9. Get est omniscient et, dans la plupart des cas, il sait exactement quand sortir de mémoire un contrôleur. Vous ne devez pas vous soucier du moment de vous débarrasser d'un contrôleur, Get connaît le meilleur moment pour le faire.
### Utilisation
```dart
// Créez la classe controller qui 'extends' GetxController
class Controller extends GetxController {
int counter = 0;
void increment() {
counter++;
update(); // utilisez update() pour mettre à jour la variable de compteur sur l'interface utilisateur lorsque incrément() est appelé
}
}
// Sur votre classe Stateless / Stateful, utilisez GetBuilder pour mettre à jour le texte lorsque incrément() est appelé
GetBuilder<Controller>(
init: Controller(), // INITIER CA UNIQUEMENT LA PREMIÈRE FOIS
builder: (_) => Text(
'${_.counter}',
),
)
//Initialisez votre contrôleur uniquement la première fois. La deuxième fois que vous utilisez ReBuilder pour le même contrôleur, ne recommencez pas. Votre contrôleur sera automatiquement supprimé de la mémoire dès que le widget qui l'a marqué comme `init` sera déployé. Vous n'avez pas à vous en soucier, Get le fera automatiquement, assurez-vous simplement de ne pas démarrer deux fois le même contrôleur.
```
**Fait!**
- Vous avez déjà appris à gérer les états avec Get.
- Note: Vous pouvez souhaiter une organisation plus grande et ne pas utiliser la propriété init. Pour cela, vous pouvez créer une classe et étendre la classe Bindings, et y mentionner les contrôleurs qui seront créés dans cette route. Les contrôleurs ne seront pas créés à ce moment-là, au contraire, il ne s'agit que d'une déclaration, de sorte que la première fois que vous utilisez un contrôleur, Get saura où chercher. Get restera lazyLoad et continuera à supprimer les contrôleurs lorsqu'ils ne seront plus nécessaires. Voir l'exemple pub.dev pour voir comment cela fonctionne.
Si vous parcourez de nombreuses routes et avez besoin de données qui se trouvaient dans votre contrôleur précédemment utilisé, il vous suffit de réutiliser GetBuilder (sans init):
```dart
class OtherClass extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GetBuilder<Controller>(
builder: (s) => Text('${s.counter}'),
),
),
);
}
```
Si vous devez utiliser votre contrôleur dans de nombreux autres endroits, et en dehors de GetBuilder, créez simplement un get dans votre contrôleur et ayez-le facilement. (ou utilisez `Get.find<Controller>()`)
```dart
class Controller extends GetxController {
/// Vous n'en avez pas besoin. Je recommande de l'utiliser uniquement pour faciliter la syntaxe.
/// avec la méthode statique: Controller.to.counter();
/// sans méthode statique: Get.find<Controller>() .counter();
/// Il n'y a aucune différence de performances, ni aucun effet secondaire de l'utilisation de l'une ou l'autre syntaxe. Un seul n'a pas besoin du type, et l'autre l'EDI le complétera automatiquement.
static Controller get to => Get.find(); // Ajouter cette ligne
int counter = 0;
void increment() {
counter++;
update();
}
}
```
Et puis vous pouvez accéder directement à votre contrôleur, de cette façon:
```dart
FloatingActionButton(
onPressed:() {
Controller.to.increment(),
} // This is incredibly simple!
child: Text("${Controller.to.counter}"),
),
```
Lorsque vous appuyez sur FloatingActionButton, tous les widgets qui écoutent la variable `counter` seront mis à jour automatiquement.
### Comment il gère les contrôleurs
Disons que nous avons ceci:
`Class a => Class B (has controller X) => Class C (has controller X)`
Dans la classe A, le contrôleur n'est pas encore en mémoire, car vous ne l'avez pas encore utilisé (Get est lazyLoad). Dans la classe B, vous avez utilisé le contrôleur et il est entré en mémoire. Dans la classe C, vous avez utilisé le même contrôleur que dans la classe B, Get partagera l'état du contrôleur B avec le contrôleur C, et le même contrôleur est toujours en mémoire. Si vous fermez l'écran C et l'écran B, Get retirera automatiquement le contrôleur X de la mémoire et libèrera des ressources, car la classe A n'utilise pas le contrôleur. Si vous naviguez à nouveau vers B, le contrôleur X entrera à nouveau en mémoire, si au lieu de passer à la classe C, vous revenez en classe A, Get retirera le contrôleur de la mémoire de la même manière. Si la classe C n'utilisait pas le contrôleur et que vous retiriez la classe B de la mémoire, aucune classe n'utiliserait le contrôleur X et de même, elle serait éliminée. La seule exception qui peut gâcher Get, est si vous supprimez B de l'itinéraire de manière inattendue et essayez d'utiliser le contrôleur dans C.Dans ce cas, l'ID de créateur du contrôleur qui était dans B a été supprimé et Get a été programmé pour supprimer de la mémoire tous les contrôleurs qui n'ont pas d'ID de créateur. Si vous avez l'intention de faire cela, ajoutez l'indicateur "autoRemove: false" au GetBuilder de la classe B et utilisez adoptID = true; dans GetBuilder de la classe C.
### Vous n'aurez plus besoin de StatefulWidgets
Utiliser StatefulWidgets signifie stocker inutilement l'état d'écrans entiers, même parce que si vous avez besoin de reconstruire au minimum un widget, vous l'intègrerez dans un Consumer / Observer / BlocProvider / GetBuilder / GetX / Obx, qui sera un autre StatefulWidget.
La classe StatefulWidget est une classe plus grande que StatelessWidget, qui allouera plus de RAM, et cela ne fera peut-être pas une différence significative entre une ou deux classes, mais cela le fera très certainement lorsque vous en aurez 100!
À moins que vous n'ayez besoin d'utiliser un mixin, comme TickerProviderStateMixin, il sera totalement inutile d'utiliser un StatefulWidget avec Get.
Vous pouvez appeler toutes les méthodes d'un StatefulWidget directement à partir d'un GetBuilder.
Si vous devez appeler la méthode initState() ou dispose() par exemple, vous pouvez les appeler directement:
```dart
GetBuilder<Controller>(
initState: (_) => Controller.to.fetchApi(),
dispose: (_) => Controller.to.closeStreams(),
builder: (s) => Text('${s.username}'),
),
```
Une bien meilleure approche que celle-ci consiste à utiliser les méthodes onInit() et onClose() directement à partir de votre contrôleur.
```dart
@override
void onInit() {
fetchApi();
super.onInit();
}
```
- NOTE: Si vous voulez démarrer une méthode au moment où le contrôleur est appelé pour la première fois, vous N'AVEZ PAS BESOIN d'utiliser des constructeurs pour cela, en fait, en utilisant un package orienté performance comme Get, cela frôle la mauvaise pratique, car il s'écarte de la logique dans laquelle les contrôleurs sont créés ou alloués (si vous créez une instance de ce contrôleur, le constructeur sera appelé immédiatement, vous remplirez un contrôleur avant même qu'il ne soit utilisé, vous allouez de la mémoire sans qu'elle ne soit utilisée , cela nuit définitivement aux principes de cette bibliothèque). Les méthodes onInit(); et onClose(); ont été créés pour cela, ils seront appelés lors de la création du Controller, ou lors de sa première utilisation, selon que vous utilisez Get.lazyPut ou non. Si vous voulez, par exemple, faire un appel à votre API pour remplir des données, vous pouvez oublier la méthode à l'ancienne de initState / dispose, lancez simplement votre appel à l'API dans onInit, et si vous devez exécuter une commande comme la fermeture des flux, utilisez onClose() pour cela.
### Pourquoi ca existe
Le but de ce package est précisément de vous donner une solution complète pour la navigation des routes, la gestion des dépendances et des états, en utilisant le moins de dépendances possible, avec un haut degré de découplage. Get engage toutes les API Flutter de haut et bas niveau en lui-même, pour vous assurer de travailler avec le moins de couplage possible. Nous centralisons tout dans un seul package, pour vous assurer que vous n'avez aucun type de couplage dans votre projet. De cette façon, vous pouvez mettre uniquement des widgets dans votre vue et laisser la partie de votre équipe qui travaille avec la `business logique` libre, pour travailler avec la business logique sans dépendre d'aucun élément de la vue. Cela fournit un environnement de travail beaucoup plus propre, de sorte qu'une partie de votre équipe ne travaille qu'avec des widgets, sans se soucier d'envoyer des données à votre contrôleur, et une partie de votre équipe ne travaille qu'avec la business logique dans toute son ampleur, sans dépendre d'aucun élément de la Vue.
Donc, pour simplifier cela:
Vous n'avez pas besoin d'appeler des méthodes dans initState et de les envoyer par paramètre à votre contrôleur, ni d'utiliser votre constructeur de contrôleur pour cela, vous avez la méthode onInit() qui est appelée au bon moment pour démarrer vos services.
Vous n'avez pas besoin d'appeler l'appareil, vous avez la méthode onClose() qui sera appelée au moment exact où votre contrôleur n'est plus nécessaire et sera supprimé de la mémoire. De cette façon, ne laissez les vues que pour les widgets, abstenez-vous d'y mettre tout type de business logique.
N'appelez pas une méthode dispose() dans GetxController, cela ne fera rien, rappelez-vous que le contrôleur n'est pas un Widget, vous ne devez pas le `supprimer`, et il sera automatiquement et intelligemment supprimé de la mémoire par Get. Si vous avez utilisé un Stream et que vous souhaitez le fermer, insérez-le simplement dans la méthode close(). Exemple:
```dart
class Controller extends GetxController {
StreamController<User> user = StreamController<User>();
StreamController<String> name = StreamController<String>();
/// pour fermer stream = méthode onClose(), pas dispose().
@override
void onClose() {
user.close();
name.close();
super.onClose();
}
}
```
Cycle de vie du controlleur:
- onInit() quand il est créé.
- onClose() quand il est fermé pour apporter des modifications en préparation de la méthode delete.
- deleted: vous n'avez pas accès à cette API car elle supprime littéralement le contrôleur de la mémoire. Il est littéralement supprimé, sans laisser de trace.
### Autres formes d utilisation
Vous pouvez utiliser l'instance Controller directement sur la valeur GetBuilder:
```dart
GetBuilder<Controller>(
init: Controller(),
builder: (value) => Text(
'${value.counter}', // ici
),
),
```
Vous pouvez également avoir besoin d'une instance de votre contrôleur en dehors de votre GetBuilder, et vous pouvez utiliser ces approches pour y parvenir:
```dart
class Controller extends GetxController {
static Controller get to => Get.find();
[...]
}
// Dans la vue:
GetBuilder<Controller>(
init: Controller(), // utilisez-le seulement la première fois sur chaque contrôleur
builder: (_) => Text(
'${Controller.to.counter}', // ici
)
),
```
ou encore
```dart
class Controller extends GetxController {
// static Controller get to => Get.find(); // sans static get
[...]
}
// Dans la classe stateful/stateless
GetBuilder<Controller>(
init: Controller(), // utilisez-le seulement la première fois sur chaque contrôleur
builder: (_) => Text(
'${Get.find<Controller>().counter}', // ici
),
),
```
- Vous pouvez utiliser des approches `non canoniques` pour ce faire. Si vous utilisez un autre gestionnaire de dépendances, comme get_it, modular, etc., et que vous souhaitez simplement fournir l'instance de contrôleur, vous pouvez le faire:
```dart
Controller controller = Controller();
[...]
GetBuilder<Controller>(
init: controller, // ici
builder: (_) => Text(
'${controller.counter}', // ici
),
),
```
### IDs Uniques
Si vous souhaitez affiner le contrôle de mise à jour d'un widget avec GetBuilder, vous pouvez leur attribuer des ID uniques:
```dart
GetBuilder<Controller>(
id: 'text'
init: Controller(), // utilisez-le seulement la première fois sur chaque contrôleur
builder: (_) => Text(
'${Get.find<Controller>().counter}', // ici
),
),
```
Et mettez-le à jour de cette façon:
```dart
update(['text']);
```
Vous pouvez également imposer des conditions pour la mise à jour:
```dart
update(['text'], counter < 10);
```
GetX le fait automatiquement et ne reconstruit que le widget qui utilise la variable exacte qui a été modifiée, si vous remplacez une variable par la même que la précédente et que cela n'implique pas un changement d'état, GetX ne reconstruira pas le widget pour économiser de la mémoire et Cycles CPU (3 est affiché à l'écran, et vous changez à nouveau la variable à 3. Dans la plupart des gestionnaires d'états, cela entraînera une nouvelle reconstruction, mais avec GetX, le widget ne sera reconstruit qu'à nouveau, si en fait son état a changé ).
## Mélanger les deux gestionnaires d'état
Certaines personnes ont ouvert une demande de fonctionnalité, car elles ne voulaient utiliser qu'un seul type de variable réactive, et les autres mécanismes, et devaient insérer un Obx dans un GetBuilder pour cela. En y réfléchissant, MixinBuilder a été créé. Il permet à la fois des changements réactifs en changeant les variables ".obs" et des mises à jour mécaniques via update(). Cependant, des 4 widgets c'est celui qui consomme le plus de ressources, car en plus d'avoir un Abonnement pour recevoir les événements de changement de ses enfants, il souscrit à la méthode de mise à jour de son contrôleur.
L'extension de GetxController est importante, car ils ont des cycles de vie et peuvent `démarrer` et `terminer` des événements dans leurs méthodes onInit() et onClose(). Vous pouvez utiliser n'importe quelle classe pour cela, mais je vous recommande fortement d'utiliser la classe GetxController pour placer vos variables, qu'elles soient observables ou non.
## GetBuilder vs GetX vs Obx vs MixinBuilder
En une décennie de travail avec la programmation, j'ai pu apprendre de précieuses leçons.
Mon premier contact avec la programmation réactive a été tellement "wow, c'est incroyable" et en fait la programmation réactive est incroyable.
Cependant, elle ne convient pas à toutes les situations. Souvent, il suffit de changer l'état de 2 ou 3 widgets en même temps, ou d'un changement d'état éphémère, auquel cas la programmation réactive n'est pas mauvaise, mais elle n'est pas appropriée.
La programmation réactive a une consommation de RAM plus élevée qui peut être compensée par le flux de travail individuel, ce qui garantira qu'un seul widget est reconstruit et si nécessaire, mais créer une liste avec 80 objets, chacun avec plusieurs flux n'est pas une bonne idée . Ouvrez le 'dart inspect' et vérifiez combien un StreamBuilder consomme, et vous comprendrez ce que j'essaie de vous dire.
Dans cet esprit, j'ai créé le gestionnaire d'état simple. C'est simple, et c'est exactement ce que vous devriez lui demander: mettre à jour l'état par blocs de manière simple et de la manière la plus économique.
GetBuilder est très économique en RAM, et il n'y a guère d'approche plus économique que lui (du moins je ne peux pas en imaginer une, si elle existe, merci de nous le faire savoir).
Cependant, GetBuilder est toujours un gestionnaire d'état mécanique, vous devez appeler update() comme vous auriez besoin d'appeler les notifyListeners() de Provider.
Il y a d'autres situations où la programmation réactive est vraiment intéressante, et ne pas travailler avec elle revient à réinventer la roue. Dans cet esprit, GetX a été créé pour fournir tout ce qui est le plus moderne et le plus avancé dans un gestionnaire d'état. Il met à jour uniquement ce qui est nécessaire et si nécessaire, si vous avez une erreur et envoyez 300 changements d'état simultanément, GetX filtrera et mettra à jour l'écran uniquement si l'état change réellement.
GetX est toujours plus économique que tout autre gestionnaire d'état réactif, mais il consomme un peu plus de RAM que GetBuilder. En y réfléchissant et en visant à maximiser la consommation de ressources, Obx a été créé. Contrairement à GetX et GetBuilder, vous ne pourrez pas initialiser un contrôleur à l'intérieur d'un Obx, c'est juste un widget avec un StreamSubscription qui reçoit les événements de changement de vos widgets enfants, c'est tout. Il est plus économique que GetX, mais perd face à GetBuilder, ce qui était prévisible, car il est réactif, et GetBuilder a l'approche la plus simpliste qui existe, de stocker le hashcode d'un widget et son StateSetter. Avec Obx, vous n'avez pas besoin d'écrire votre type de contrôleur, et vous pouvez entendre le changement de plusieurs contrôleurs différents, mais il doit être initialisé avant, soit en utilisant l'approche d'exemple au début de ce readme, soit en utilisant la classe Bindings.
\ No newline at end of file
... ...