Rafa Ruiz
Committed by GitHub

Merge pull request #1 from jonataslaw/master

Update

Too many changes to show.

To preserve performance only 40 of 40+ files are displayed.

@@ -23,7 +23,7 @@ jobs: @@ -23,7 +23,7 @@ jobs:
23 # https://github.com/marketplace/actions/flutter-action 23 # https://github.com/marketplace/actions/flutter-action
24 - uses: subosito/flutter-action@v1 24 - uses: subosito/flutter-action@v1
25 with: 25 with:
26 - flutter-version: "1.22.3" 26 + flutter-version: "2.0.2"
27 channel: "stable" 27 channel: "stable"
28 - run: flutter pub get 28 - run: flutter pub get
29 #- run: flutter analyze 29 #- run: flutter analyze
  1 +# This file tracks properties of this Flutter project.
  2 +# Used by Flutter tool to assess capabilities and perform upgrades etc.
  3 +#
  4 +# This file should be version controlled and should not be manually edited.
  5 +
  6 +version:
  7 + revision: 60bd88df915880d23877bfc1602e8ddcf4c4dd2a
  8 + channel: stable
  9 +
  10 +project_type: app
  1 +## [4.0.3]
  2 +- Added new linter rules to improve score
  3 +
  4 +## [4.0.2]
  5 +- Removed "!" of if else conditions until the null-safety of the dart is consistent for using it.
  6 +
  7 +## [4.0.1]
  8 +- Fix changelog
  9 +
  10 +## [4.0.0]
  11 +- Added append function to StateMixin. Now is possible track loading, success and error handle of your application with ONE LINE OF CODE. Ex: append(()=> api.getUser);
  12 +- Migrate to null-safety
  13 +- Added ScrollMixin to controllers
  14 +- Added loadingMore status to RxStatus
  15 +- Fix content-type qual null (@katekko)
  16 +- Made GetInstance non nullable (@eduardoflorence)
  17 +- Fix multi-parameters url (@iMrLopez)
  18 +- Fix Expected value of SkDeletable error (@obadajasm)
  19 +- Added triggers, an Rx method that triggers events, even if they are the same as the previous event (@RafaRuiz)
  20 +- Improve docs: (@CNAD666), (@dhhAndroid), (@Jackylee1992),
  21 +
  22 +Switching to null-safety:
  23 +You can continue using GetX as normal, with as little breaking changes as possible.
  24 +It is still possible to declare the var.obs variable, and this remains the preferred way, forcing null-safety and giving you all the security that sound null-safety delivers to your app. However, if you need to use null, we also provide a solution for you.
  25 +Declare the variables with `?` Ex: `final Rx<int?> count = 0.obs`.
  26 +You can also use custom Rxn types with null-safety:
  27 +`RxInt` == not nullable
  28 +`RxnInt` == nullable.
  29 +
  30 +## [3.25.6]
  31 +- Added documentation in French (@kamazoun)
  32 +- Fix logs messages (@damphat)
  33 +- Fix plural to zero on internacionalization (@RafaRuiz)
  34 +- Fix error when body hasn't content on GetConnect (@jasonlaw)
  35 +- Fix typos on readme (@bashleigh)
  36 +- Fix group updates to GetBuilder
  37 +
  38 +## [3.25.5]
  39 +- Fix Get.isDialogOpen when two or more open dialogs are closed
  40 +
1 ## [3.25.4] 41 ## [3.25.4]
2 - Added logs and tests to unknownRoute 42 - Added logs and tests to unknownRoute
3 43
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -*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).* 3 +*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).*
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg) 6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
@@ -136,7 +136,7 @@ class Home extends StatelessWidget { @@ -136,7 +136,7 @@ class Home extends StatelessWidget {
136 appBar: AppBar(title: Obx(() => Text("Clicks: " + c.count.string))), 136 appBar: AppBar(title: Obx(() => Text("Clicks: " + c.count.string))),
137 137
138 // Reemplace el Navigator.push de 8 líneas por un simple Get.to(). No necesitas contexto 138 // Reemplace el Navigator.push de 8 líneas por un simple Get.to(). No necesitas contexto
139 - body: Center(child: RaisedButton( 139 + body: Center(child: ElevatedButton(
140 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 140 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
141 floatingActionButton: 141 floatingActionButton:
142 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 142 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
  1 +![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
  2 +
  3 +**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).**
  4 +
  5 +[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
  6 +[![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
  7 +![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
  8 +[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
  9 +[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
  10 +[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx)
  11 +[![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
  12 +<a href="https://github.com/Solido/awesome-flutter">
  13 +<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
  14 +</a>
  15 +<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>
  16 +
  17 +![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
  18 +
  19 +- [A Propos de Get](#a-propos-de-get)
  20 +- [Installation](#installation)
  21 +- [L'application 'Counter' avec GetX](#application-counter-avec-getx)
  22 +- [Les trois pilliers](#les-trois-pilliers)
  23 + - [Gestion d'état (State management)](#gestion-d-etat)
  24 + - [Gestionnaire d'état réactif (Reactive State Manager)](#gestionnaire-d-etat-reactif)
  25 + - [Plus de détails sur la gestion d'état](#plus-de-details-sur-la-gestion-d-etat)
  26 + - [Gestion de route](#gestion-de-route)
  27 + - [Plus de détails sur la gestion de route](#plus-de-details-sur-la-gestion-de-route)
  28 + - [Gestion des dépendances](#gestion-des-dependances)
  29 + - [Plus de détails sur la gestion des dépendances](#plus-de-details-sur-la-gestion-des-dependances)
  30 +- [Utils](#utils)
  31 + - [Internationalization](#internationalization)
  32 + - [Traductions](#traductions)
  33 + - [Utiliser les traductions](#utiliser-les-traductions)
  34 + - [Locales](#locales)
  35 + - [Changer la locale](#changer-la-locale)
  36 + - [Locale du Système](#locale-du-systeme)
  37 + - [Changer le Thème](#changer-le-theme)
  38 + - [GetConnect](#getconnect)
  39 + - [Configuration par défaut](#configuration-par-defaut)
  40 + - [Configuration personnalisée](#configuration-personnalisee)
  41 + - [Middleware GetPage](#middleware-getpage)
  42 + - [Priority](#priority)
  43 + - [Redirect](#redirect)
  44 + - [onPageCalled](#onpagecalled)
  45 + - [OnBindingsStart](#onbindingsstart)
  46 + - [OnPageBuildStart](#onpagebuildstart)
  47 + - [OnPageBuilt](#onpagebuilt)
  48 + - [OnPageDispose](#onpagedispose)
  49 + - [Autres APIs](#autres-apis)
  50 + - [Paramètres globaux et configurations manuelles facultatifs](#parametres-globaux-et-configurations-manuelles-facultatifs)
  51 + - [State Widgets Locaux](#state-widgets-locaux)
  52 + - [ValueBuilder](#valuebuilder)
  53 + - [ObxValue](#obxvalue)
  54 + - [Conseils utiles](#conseils-utiles)
  55 + - [GetView](#getview)
  56 + - [GetResponsiveView](#getresponsiveview)
  57 + - [Guide d'utilisation](#guide-d-utilisation)
  58 + - [GetWidget](#getwidget)
  59 + - [GetxService](#getxservice)
  60 +- [Changements par rapport à 2.0](#changements-par-rapport-a-20)
  61 +- [Pourquoi Getx?](#pourquoi-getx)
  62 +- [Communité](#communite)
  63 + - [Chaînes communautaires](#chaines-communautaires)
  64 + - [Comment contribuer](#comment-contribuer)
  65 + - [Articles et videos](#articles-et-videos)
  66 +
  67 +# A Propos de Get
  68 +
  69 +- 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.
  70 +
  71 +- 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.**
  72 +
  73 + - **PERFORMANCE:** GetX se concentre sur la performance et la consommation minimale de ressources. GetX n'utilise ni Streams ni ChangeNotifier.
  74 +
  75 + - **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.
  76 +
  77 + 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).
  78 +
  79 + - **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.
  80 +
  81 + 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.
  82 + 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''.
  83 + 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.
  84 +
  85 +- 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é.
  86 +
  87 +- 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.
  88 + **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)**.
  89 +
  90 +**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)**.
  91 +
  92 +**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)**
  93 +
  94 +# Installation
  95 +
  96 +Ajoutez Get à votre fichier pubspec.yaml:
  97 +
  98 +```yaml
  99 +dependencies:
  100 + get:
  101 +```
  102 +
  103 +Importez Get dans les fichiers dans lesquels il doit être utilisé:
  104 +
  105 +```dart
  106 +import 'package:get/get.dart';
  107 +```
  108 +
  109 +# Application Counter avec Getx
  110 +
  111 +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.
  112 +- Step 1:
  113 + Ajoutez "Get" avant MaterialApp, pour le transformer en GetMaterialApp
  114 +
  115 +```dart
  116 +void main() => runApp(GetMaterialApp(home: Home()));
  117 +```
  118 +
  119 +- 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'.
  120 +
  121 +- 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.
  122 +
  123 +- Step 2:
  124 + Créez votre classe de Business logic et placez-y toutes les variables, méthodes et contrôleurs.
  125 + Vous pouvez rendre toute variable observable en utilisant un simple ".obs".
  126 +
  127 +```dart
  128 +class Controller extends GetxController{
  129 + var count = 0.obs;
  130 + increment() => count++;
  131 +}
  132 +```
  133 +
  134 +- Step 3:
  135 + Créez votre Vue, utilisez StatelessWidget et économisez de la RAM, avec Get, vous n'aurez peut-être plus besoin d'utiliser StatefulWidget.
  136 +
  137 +```dart
  138 +class Home extends StatelessWidget {
  139 +
  140 + @override
  141 + Widget build(context) {
  142 +
  143 + // Instanciez votre classe en utilisant Get.put() pour le rendre disponible pour tous les routes "descendantes".
  144 + final Controller c = Get.put(Controller());
  145 +
  146 + return Scaffold(
  147 + // Utilisez Obx(()=> pour mettre à jour Text() chaque fois que count est changé.
  148 + appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
  149 +
  150 + // Remplacez les 8 lignes Navigator.push par un simple Get.to(). Vous n'avez pas besoin de 'context'
  151 + body: Center(child: ElevatedButton(
  152 + child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
  153 + floatingActionButton:
  154 + FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
  155 + }
  156 +}
  157 +
  158 +class Other extends StatelessWidget {
  159 + // Vous pouvez demander à Get de trouver un contrôleur utilisé par une autre page et de vous y rediriger.
  160 + final Controller c = Get.find();
  161 +
  162 + @override
  163 + Widget build(context){
  164 + // Accéder à la variable 'count' qui est mise à jour
  165 + return Scaffold(body: Center(child: Text("${c.count}")));
  166 + }
  167 +}
  168 +```
  169 +
  170 +Résultat:
  171 +
  172 +![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/counter-app-gif.gif)
  173 +
  174 +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.
  175 +
  176 +Get a été conçu pour fonctionner avec des équipes, mais il simplifie le travail d'un développeur individuel.
  177 +
  178 +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!
  179 +
  180 +# Les trois pilliers
  181 +
  182 +## Gestion d Etat
  183 +
  184 +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).
  185 +
  186 +### Gestionnaire d Etat Reactif
  187 +
  188 +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:
  189 +
  190 +- Vous n'aurez pas besoin de créer des StreamControllers.
  191 +- Vous n'aurez pas besoin de créer un StreamBuilder pour chaque variable
  192 +- Vous n'aurez pas besoin de créer une classe pour chaque état.
  193 +- Vous n'aurez pas besoin de créer un 'get' pour une valeur initiale.
  194 +- Vous n'aurez pas besoin d'utiliser des générateurs de code
  195 +
  196 +La programmation réactive avec Get est aussi simple que d'utiliser setState.
  197 +
  198 +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.
  199 +
  200 +Voici votre variable:
  201 +
  202 +```dart
  203 +var name = 'Jonatas Borges';
  204 +```
  205 +
  206 +Pour la rendre observable, il vous suffit d'ajouter ".obs" à la fin:
  207 +
  208 +```dart
  209 +var name = 'Jonatas Borges'.obs;
  210 +```
  211 +
  212 +Et dans l'interface utilisateur, lorsque vous souhaitez afficher cette valeur et mettre à jour l'écran chaque fois qu'elle change, faites simplement:
  213 +
  214 +```dart
  215 +Obx(() => Text("${controller.name}"));
  216 +```
  217 +
  218 +C'est _tout_. Si simple que ca.
  219 +
  220 +### Plus de details sur la gestion d Etat
  221 +
  222 +**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.**
  223 +
  224 +Vous pourrez vous faire une meilleure idée de la puissance de GetX.
  225 +
  226 +## Gestion de route
  227 +
  228 +Si vous envisagez d'utiliser des routes/snackbars/dialogs/bottomsheets sans 'context', GetX est également excellent pour vous, voyez par vous-même:
  229 +
  230 +Ajoutez "Get" avant votre MaterialApp, en le transformant en GetMaterialApp
  231 +
  232 +```dart
  233 +GetMaterialApp( // Avant: MaterialApp(
  234 + home: MyHome(),
  235 +)
  236 +```
  237 +
  238 +Accédez à un nouvel écran:
  239 +
  240 +```dart
  241 +
  242 +Get.to(ÉcranSuivant());
  243 +```
  244 +
  245 +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)
  246 +
  247 +```dart
  248 +
  249 +Get.toNamed('/details');
  250 +```
  251 +
  252 +Pour fermer des snackbars, dialogs, bottomsheets, ou tout ce que vous auriez normalement fermé avec Navigator.pop(context);
  253 +
  254 +```dart
  255 +Get.back();
  256 +```
  257 +
  258 +Pour aller à l'écran suivant avec aucune option pour revenir à l'écran précédent (pour une utilisation dans SplashScreens, écrans de connexion, etc.)
  259 +
  260 +```dart
  261 +Get.off(NextScreen());
  262 +```
  263 +
  264 +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)
  265 +
  266 +```dart
  267 +Get.offAll(NextScreen());
  268 +```
  269 +
  270 +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.
  271 +
  272 +### Plus de details sur la gestion de route
  273 +
  274 +**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)**
  275 +
  276 +## Gestion des dependances
  277 +
  278 +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:
  279 +
  280 +```dart
  281 +Controller controller = Get.put(Controller()); // Au lieu de Controller controller = Controller();
  282 +```
  283 +
  284 +- 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.
  285 +
  286 +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.
  287 +Vous pouvez donc utiliser votre contrôleur (ou classe Bloc) normalement.
  288 +
  289 +**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.
  290 +
  291 +```dart
  292 +controller.fetchApi();
  293 +```
  294 +
  295 +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:
  296 +```dart
  297 +Controller controller = Get.find();
  298 +//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.
  299 +```
  300 +
  301 +Et puis vous pourrez récupérer les données de votre contrôleur obtenu précédemment:
  302 +
  303 +```dart
  304 +Text(controller.textFromApi);
  305 +```
  306 +
  307 +### Plus de details sur la gestion des dependances
  308 +
  309 +**Trouvez une explication plus détaillée sur la gestion des dépendances [ici](./documentation/fr_FR/dependency_management.md)**
  310 +
  311 +# Utils
  312 +
  313 +## Internationalization
  314 +
  315 +### Traductions
  316 +
  317 +Les traductions sont enregistrées sous forme de dictionaire clé-valeur simple.
  318 +Pour ajouter des traductions, créez une classe qui 'extend' `Translations`.
  319 +
  320 +```dart
  321 +import 'package:get/get.dart';
  322 +
  323 +class Messages extends Translations {
  324 + @override
  325 + Map<String, Map<String, String>> get keys => {
  326 + 'en_US': {
  327 + 'hello': 'Hello World',
  328 + },
  329 + 'de_DE': {
  330 + 'hello': 'Hallo Welt',
  331 + }
  332 + };
  333 +}
  334 +```
  335 +
  336 +#### Utiliser les traductions
  337 +
  338 +Ajouter juste `.tr` à la clé et elle sera traduite selon la valeur actuelle `Get.locale` et de `Get.fallbackLocale`.
  339 +
  340 +```dart
  341 +Text('title'.tr);
  342 +```
  343 +
  344 +#### Utiliser les traductions avec le singulier et le pluriel
  345 +
  346 +```dart
  347 +var products = [];
  348 +Text('cléAuSingulier'.trPlural('cléAuPluriel', products.length, Args));
  349 +```
  350 +
  351 +#### Utiliser les traductions avec paramètres
  352 +
  353 +```dart
  354 +import 'package:get/get.dart';
  355 +
  356 +
  357 +Map<String, Map<String, String>> get keys => {
  358 + 'en_US': {
  359 + 'logged_in': 'logged in as @name with email @email',
  360 + },
  361 + 'es_ES': {
  362 + 'logged_in': 'iniciado sesión como @name con e-mail @email',
  363 + }
  364 +};
  365 +
  366 +Text('logged_in'.trParams({
  367 + 'name': 'Jhon',
  368 + 'email': 'jhon@example.com'
  369 + }));
  370 +```
  371 +
  372 +### Locales
  373 +
  374 +'Locales' signifie lieux.
  375 +Pour definir les traductions, passer les paramètres 'locale' et 'translations' à GetMaterialApp.
  376 +
  377 +```dart
  378 +return GetMaterialApp(
  379 + translations: Messages(), // Vos traductions
  380 + locale: Locale('en', 'US'), // Les traductions seront faites dans cette 'locale' (langue)
  381 + fallbackLocale: Locale('en', 'UK'), // definit le 'language de secours' au cas oú un language invalide est sélectionné.
  382 +);
  383 +```
  384 +
  385 +#### Changer la locale
  386 +
  387 +Appelez `Get.updateLocale (locale)` pour mettre à jour la locale. Les traductions utilisent alors automatiquement la nouvelle langue.
  388 +
  389 +```dart
  390 +var locale = Locale('en', 'US');
  391 +Get.updateLocale(locale);
  392 +```
  393 +
  394 +#### Locale du systeme
  395 +
  396 +Pour lire les paramètres régionaux ('locales') du système, vous pouvez utiliser `Get.deviceLocale`.
  397 +
  398 +```dart
  399 +return GetMaterialApp(
  400 + locale: Get.deviceLocale,
  401 +);
  402 +```
  403 +
  404 +## Changer le Theme
  405 +
  406 +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 ™**.
  407 +
  408 +Vous pouvez créer votre thème personnalisé et l'ajouter simplement dans `Get.changeTheme` sans aucune préconfiguration pour cela:
  409 +
  410 +```dart
  411 +Get.changeTheme(ThemeData.light());
  412 +```
  413 +
  414 +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:
  415 +
  416 +- L'API qui vérifie si le "Thème" sombre est utilisé.
  417 +- Et l'API de changement de thème, vous pouvez simplement le mettre dans un 'onPressed':
  418 +
  419 +```dart
  420 +Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());
  421 +```
  422 +
  423 +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_.
  424 +
  425 +## GetConnect
  426 +
  427 +GetConnect est un moyen facile de communiquer de votre backend à votre frontend avec http ou websockets.
  428 +
  429 +### Configuration par defaut
  430 +
  431 +Vous pouvez simplement 'extends' GetConnect et utiliser les méthodes GET / POST / PUT / DELETE / SOCKET pour communiquer avec votre API Rest ou vos websockets.
  432 +
  433 +```dart
  434 +class UserProvider extends GetConnect {
  435 + // Get request
  436 + Future<Response> getUser(int id) => get('http://youapi/users/$id');
  437 + // Post request
  438 + Future<Response> postUser(Map data) => post('http://youapi/users', body: data);
  439 + // Post request with File
  440 + Future<Response<CasesModel>> postCases(List<int> image) {
  441 + final form = FormData({
  442 + 'file': MultipartFile(image, filename: 'avatar.png'),
  443 + 'otherFile': MultipartFile(image, filename: 'cover.png'),
  444 + });
  445 + return post('http://youapi/users/upload', form);
  446 + }
  447 +
  448 + GetSocket userMessages() {
  449 + return socket('https://yourapi/users/socket');
  450 + }
  451 +}
  452 +```
  453 +
  454 +### Configuration personnalisee
  455 +
  456 +
  457 +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.
  458 +
  459 +```dart
  460 +class HomeProvider extends GetConnect {
  461 + @override
  462 + void onInit() {
  463 + // Toute 'Request' passera à jsonEncode donc CasesModel.fromJson()
  464 + httpClient.defaultDecoder = CasesModel.fromJson;
  465 + httpClient.baseUrl = 'https://api.covid19api.com';
  466 + // baseUrl = 'https://api.covid19api.com';
  467 + // Il définit baseUrl pour Http et websockets si utilisé sans instance [httpClient]
  468 +
  469 + // Cela attachera la propriété 'apikey' sur l'en-tête ('header') de toutes les 'request's
  470 + httpClient.addRequestModifier((request) {
  471 + request.headers['apikey'] = '12345678';
  472 + return request;
  473 + });
  474 +
  475 + // Même si le serveur envoie des données avec le pays "Brésil",
  476 + // cela ne sera jamais affiché aux utilisateurs, car vous supprimez
  477 + // ces données de la réponse, même avant que la réponse ne soit délivrée
  478 + httpClient.addResponseModifier<CasesModel>((request, response) {
  479 + CasesModel model = response.body;
  480 + if (model.countries.contains('Brazil')) {
  481 + model.countries.remove('Brazil');
  482 + }
  483 + });
  484 +
  485 + httpClient.addAuthenticator((request) async {
  486 + final response = await get("http://yourapi/token");
  487 + final token = response.body['token'];
  488 + // Définit l'en-tête
  489 + request.headers['Authorization'] = "$token";
  490 + return request;
  491 + });
  492 +
  493 + // L'Autenticator sera appelé 3 fois si HttpStatus est HttpStatus.unauthorized
  494 + httpClient.maxAuthRetries = 3;
  495 + }
  496 +
  497 +
  498 + @override
  499 + Future<Response<CasesModel>> getCases(String path) => get(path);
  500 +}
  501 +```
  502 +
  503 +## Middleware GetPage
  504 +
  505 +GetPage a maintenant une nouvelle propriété qui prend une liste de GetMiddleWare et les exécute dans l'ordre spécifique.
  506 +
  507 +**Note**: Lorsque GetPage a un Middleware, tous les enfants de cette page auront automatiquement les mêmes middlewares.
  508 +
  509 +### Priority
  510 +
  511 +L'ordre des middlewares à exécuter peut être défini par la priorité dans GetMiddleware.
  512 +
  513 +```dart
  514 +final middlewares = [
  515 + GetMiddleware(priority: 2),
  516 + GetMiddleware(priority: 5),
  517 + GetMiddleware(priority: 4),
  518 + GetMiddleware(priority: -8),
  519 +];
  520 +```
  521 +
  522 +ces middlewares seront exécutés dans cet ordre **-8 => 2 => 4 => 5**
  523 +
  524 +### Redirect
  525 +
  526 + 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.
  527 +
  528 +```dart
  529 +GetPage redirect( ) {
  530 + final authService = Get.find<AuthService>();
  531 + return authService.authed.value ? null : RouteSettings(name: '/login');
  532 +}
  533 +```
  534 +
  535 +### onPageCalled
  536 +
  537 +Cette fonction sera appelée lorsque cette page sera appelée.
  538 +Vous pouvez l'utiliser pour changer quelque chose sur la page ou lui donner une nouvelle page.
  539 +
  540 +```dart
  541 +GetPage onPageCalled(GetPage page) {
  542 + final authService = Get.find<AuthService>();
  543 + return page.copyWith(title: 'Welcome ${authService.UserName}');
  544 +}
  545 +```
  546 +
  547 +### OnBindingsStart
  548 +
  549 +Cette fonction sera appelée juste avant l'initialisation des liaisons ('bidings').
  550 +Ici, vous pouvez modifier les liaisons de cette page.
  551 +
  552 +```dart
  553 +List<Bindings> onBindingsStart(List<Bindings> bindings) {
  554 + final authService = Get.find<AuthService>();
  555 + if (authService.isAdmin) {
  556 + bindings.add(AdminBinding());
  557 + }
  558 + return bindings;
  559 +}
  560 +```
  561 +
  562 +### OnPageBuildStart
  563 +
  564 +Cette fonction sera appelée juste après l'initialisation des liaisons ('bidings').
  565 +Ici, vous pouvez faire quelque chose après avoir créé les liaisons et avant de créer le widget de page.
  566 +
  567 +```dart
  568 +GetPageBuilder onPageBuildStart(GetPageBuilder page) {
  569 + print('les liaisons sont prêtes');
  570 + return page;
  571 +}
  572 +```
  573 +
  574 +### OnPageBuilt
  575 +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é.
  576 +
  577 +### OnPageDispose
  578 +
  579 +Cette fonction sera appelée juste après avoir disposé tous les objets associés (contrôleurs, vues, ...) à la page.
  580 +
  581 +## Autres APIs
  582 +
  583 +```dart
  584 +// donne les arguments actuels de currentScreen
  585 +Get.arguments
  586 +
  587 +// donne le nom de l'itinéraire précédent
  588 +Get.previousRoute
  589 +
  590 +// donne la route brute d'accès par exemple, rawRoute.isFirst()
  591 +Get.rawRoute
  592 +
  593 +// donne accès à l'API de routing de GetObserver
  594 +Get.routing
  595 +
  596 +// vérifier si le snackbar est ouvert
  597 +Get.isSnackbarOpen
  598 +
  599 +// vérifier si la boîte de dialogue est ouverte
  600 +Get.isDialogOpen
  601 +
  602 +// vérifie si la bottomSheet est ouverte
  603 +Get.isBottomSheetOpen
  604 +
  605 +// supprime une route.
  606 +Get.removeRoute()
  607 +
  608 +// retourne à plusieurs reprises jusqu'à ce que le prédicat retourne 'true'.
  609 +Get.until()
  610 +
  611 +// passe à la route suivante et supprime toutes les routes précédentes jusqu'à ce que le prédicat retourne 'true'.
  612 +Get.offUntil()
  613 +
  614 +// passe à la route nommée suivante et supprime toutes les routes précédentes jusqu'à ce que le prédicat retourne 'true'.
  615 +Get.offNamedUntil()
  616 +
  617 +// Vérifie sur quelle plate-forme l'application s'exécute
  618 +GetPlatform.isAndroid
  619 +GetPlatform.isIOS
  620 +GetPlatform.isMacOS
  621 +GetPlatform.isWindows
  622 +GetPlatform.isLinux
  623 +GetPlatform.isFuchsia
  624 +
  625 +// Vérifie le type d'appareil
  626 +GetPlatform.isMobile
  627 +GetPlatform.isDesktop
  628 +// Toutes les plates-formes sont prises en charge indépendamment, dans le Web!
  629 +// Vous pouvez dire si vous utilisez un navigateur
  630 +// sur Windows, iOS, OSX, Android, etc.
  631 +GetPlatform.isWeb
  632 +
  633 +
  634 +// Équivaut à: MediaQuery.of(context).size.height,
  635 +// mais immuable.
  636 +Get.height
  637 +Get.width
  638 +
  639 +// Donne le 'context' actuel de 'Navigator'.
  640 +Get.context
  641 +
  642 +// Donne le contexte du snackbar / dialogue / bottomsheet au premier plan, n'importe où dans votre code.
  643 +Get.contextOverlay
  644 +
  645 +// Remarque: les méthodes suivantes sont des extensions sur le 'context'. Puisque vous
  646 +// 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
  647 +
  648 +// 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.
  649 +context.width
  650 +context.height
  651 +
  652 +// Vous donne le pouvoir de définir la moitié de l'écran, un tiers de celui-ci et ainsi de suite.
  653 +// Utile pour les applications responsives.
  654 +// paramètre dividedBy (double) optionnel - par défaut: 1
  655 +// paramètre reducedBy (double) facultatif - par défaut: 0
  656 +context.heightTransformer ()
  657 +context.widthTransformer ()
  658 +
  659 +/// Similaire à MediaQuery.of(context).size
  660 +context.mediaQuerySize()
  661 +
  662 +/// Similaire à MediaQuery.of(context).padding
  663 +context.mediaQueryPadding()
  664 +
  665 +/// Similaire à MediaQuery.of(context).viewPadding
  666 +context.mediaQueryViewPadding()
  667 +
  668 +/// Similaire à MediaQuery.of(context).viewInsets;
  669 +context.mediaQueryViewInsets()
  670 +
  671 +/// Similaire à MediaQuery.of(context).orientation;
  672 +context.orientation()
  673 +
  674 +/// Vérifie si l'appareil est en mode paysage
  675 +context.isLandscape()
  676 +
  677 +/// Vérifie si l'appareil est en mode portrait
  678 +context.isPortrait()
  679 +
  680 +/// Similaire à MediaQuery.of(context).devicePixelRatio;
  681 +context.devicePixelRatio()
  682 +
  683 +/// Similaire à MediaQuery.of(context).textScaleFactor;
  684 +context.textScaleFactor()
  685 +
  686 +/// Obtenir le côté le plus court de l'écran
  687 +context.mediaQueryShortestSide()
  688 +
  689 +/// Vrai si la largeur est supérieure à 800p
  690 +context.showNavbar()
  691 +
  692 +/// Vrai si le côté le plus court est inférieur à 600p
  693 +context.isPhone()
  694 +
  695 +/// Vrai si le côté le plus court est plus grand que 600p
  696 +context.isSmallTablet()
  697 +
  698 +/// Vrai si le côté le plus court est plus grand que 720p
  699 +context.isLargeTablet()
  700 +
  701 +/// Vrai si l'appareil actuel est une tablette
  702 +context.isTablet()
  703 +
  704 +/// Renvoie une valeur <T> en fonction de la taille de l'écran
  705 +/// peut donner une valeur pour:
  706 +/// watch: si le côté le plus court est inférieur à 300
  707 +/// mobile: si le côté le plus court est inférieur à 600
  708 +/// tablette: si le côté le plus court est inférieur à 1200
  709 +/// bureautique: si la largeur est supérieure à 1200
  710 +context.responsiveValue<T>()
  711 +```
  712 +
  713 +### Parametres globaux et configurations manuelles facultatifs
  714 +
  715 +GetMaterialApp configure tout pour vous, mais si vous souhaitez configurer Get manuellement:
  716 +
  717 +```dart
  718 +MaterialApp(
  719 + navigatorKey: Get.key,
  720 + navigatorObservers: [GetObserver()],
  721 +);
  722 +```
  723 +
  724 +Vous pourrez également utiliser votre propre middleware dans `GetObserver`, cela n'influencera rien.
  725 +
  726 +```dart
  727 +MaterialApp(
  728 + navigatorKey: Get.key,
  729 + navigatorObservers: [
  730 + GetObserver(MiddleWare.observer) // Ici
  731 + ],
  732 +);
  733 +```
  734 +
  735 +Vous pouvez créer _Global Settings_ pour `Get`. Ajoutez simplement `Get.config` à votre code avant de changer de route.
  736 +Ou faites-le directement dans votre `GetMaterialApp`
  737 +
  738 +```dart
  739 +GetMaterialApp(
  740 + enableLog: true,
  741 + defaultTransition: Transition.fade,
  742 + opaqueRoute: Get.isOpaqueRouteDefault,
  743 + popGesture: Get.isPopGestureEnable,
  744 + transitionDuration: Get.defaultDurationTransition,
  745 + defaultGlobalState: Get.defaultGlobalState,
  746 +);
  747 +
  748 +Get.config(
  749 + enableLog = true,
  750 + defaultPopGesture = true,
  751 + defaultTransition = Transitions.cupertino
  752 +)
  753 +```
  754 +
  755 +Vous pouvez éventuellement rediriger tous les messages de journalisation (logging) de `Get`.
  756 +Si vous souhaitez utiliser votre propre package de journalisation préféré,
  757 +et souhaitez capturer les logs là-bas:
  758 +
  759 +```dart
  760 +GetMaterialApp(
  761 + enableLog: true,
  762 + logWriterCallback: localLogWriter,
  763 +);
  764 +
  765 +void localLogWriter(String text, {bool isError = false}) {
  766 + // transmettez le message à votre package de journalisation préféré ici
  767 + // veuillez noter que même si enableLog: false, les messages du journal seront poussés dans ce 'callback'
  768 + // vérifiez le 'flag' si vous le souhaitez via GetConfig.isLogEnable
  769 +}
  770 +
  771 +```
  772 +
  773 +### State Widgets Locaux
  774 +
  775 +Ces Widgets vous permettent de gérer une valeur unique, et de garder l'état éphémère et localement.
  776 +Nous avons des saveurs pour réactif et simple.
  777 +Par exemple, vous pouvez les utiliser pour basculer obscureText dans un `TextField`, peut-être créer un
  778 +Panneau extensible, ou peut-être modifier l'index actuel dans `BottomNavigationBar` tout en modifiant le contenu
  779 +de 'body' dans un `Scaffold`.
  780 +
  781 +#### ValueBuilder
  782 +
  783 +Une simplification de `StatefulWidget` qui fonctionne avec un callback `.setState` qui prend la valeur mise à jour.
  784 +
  785 +```dart
  786 +ValueBuilder<bool>(
  787 + initialValue: false,
  788 + builder: (value, updateFn) => Switch(
  789 + value: value,
  790 + onChanged: updateFn, // même signature! vous pouvez utiliser (newValue) => updateFn (newValue)
  791 + ),
  792 + // si vous devez appeler quelque chose en dehors de la méthode du builder.
  793 + onUpdate: (value) => print("Valeur mise à jour: $value"),
  794 + onDispose: () => print("Widget détruit"),
  795 +),
  796 +```
  797 +
  798 +#### ObxValue
  799 +
  800 +Similaire à [`ValueBuilder`](#valuebuilder), mais c'est la version Reactive, vous passez une instance Rx (rappelez-vous les .obs magiques?) et il
  801 + se met à jour automatiquement ... n'est-ce pas génial?
  802 +
  803 +```dart
  804 +ObxValue((data) => Switch(
  805 + value: data.value,
  806 + onChanged: data, // Rx a une fonction _callable_! Vous pouvez utiliser (flag) => data.value = flag,
  807 + ),
  808 + false.obs,
  809 +),
  810 +```
  811 +
  812 +## Conseils utiles
  813 +
  814 +`.obs`ervables (également appelés types _Rx_) ont une grande variété de méthodes et d'opérateurs internes.
  815 +
  816 +> Il est très courant de croire qu'une propriété avec `.obs` ** EST ** la valeur réelle ... mais ne vous y trompez pas!
  817 +> Nous évitons la déclaration Type de la variable, car le compilateur de Dart est assez intelligent, et le code
  818 +> semble plus propre, mais:
  819 +
  820 +```dart
  821 +var message = 'Hello world'.obs;
  822 +print( 'Message "$message" est de Type ${message.runtimeType}');
  823 +```
  824 +
  825 +Bien que `message` _prints_ la vraie valeur du String, le Type est **RxString**!
  826 +
  827 +Donc, vous ne pouvez pas faire `message.substring( 0, 4 )`.
  828 +Vous devez utiliser la vraie `valeur` dans _observable_:
  829 +La façon "la plus utilisée" est `.value`, mais, que vous pouviez aussi...
  830 +
  831 +```dart
  832 +final name = 'GetX'.obs;
  833 +// "met à jour" le flux, uniquement si la valeur est différente de la valeur actuelle.
  834 +name.value = 'Hey';
  835 +
  836 +// Toutes les propriétés Rx sont "appelables" et renvoie la nouvelle valeur.
  837 +// mais cette approche n'accepte pas `null`, l'interface utilisateur ne sera pas reconstruite.
  838 +name('Hello');
  839 +
  840 +// est comme un getter, affiche `Hello`.
  841 +name() ;
  842 +
  843 +/// nombres:
  844 +
  845 +final count = 0.obs;
  846 +
  847 +// Vous pouvez utiliser toutes les opérations non mutables à partir de num primitives!
  848 +count + 1;
  849 +
  850 +// Fais attention! ceci n'est valable que si `count` n'est pas final, mais var
  851 +count += 1;
  852 +
  853 +// Vous pouvez également comparer avec des valeurs:
  854 +count > 2;
  855 +
  856 +/// booleans:
  857 +
  858 +final flag = false.obs;
  859 +
  860 +// bascule la valeur entre true / false
  861 +flag.toggle();
  862 +
  863 +
  864 +/// tous les types:
  865 +
  866 +// Définit la `valeur` sur null.
  867 +flag.nil();
  868 +
  869 +// Toutes les opérations toString (), toJson () sont transmises à la `valeur`
  870 +print( count ); // appelle `toString ()` à l'intérieur de RxInt
  871 +
  872 +final abc = [0,1,2].obs;
  873 +// Convertit la valeur en un Array json, affiche RxList
  874 +// Json est pris en charge par tous les types Rx!
  875 +print('json: ${jsonEncode(abc)}, type: ${abc.runtimeType}');
  876 +
  877 +// RxMap, RxList et RxSet sont des types Rx spéciaux, qui étendent leurs types natifs.
  878 +// mais vous pouvez travailler avec une liste comme une liste régulière, bien qu'elle soit réactive!
  879 +abc.add(12); // pousse 12 dans la liste et MET À JOUR le flux.
  880 +abc[3]; // comme Lists, lit l'index 3.
  881 +
  882 +
  883 +// l'égalité fonctionne avec le Rx et la valeur, mais hashCode est toujours pris à partir de la valeur
  884 +final number = 12.obs;
  885 +print( number == 12 ); // retource > true
  886 +
  887 +/// Modèles Rx personnalisés:
  888 +
  889 +// toJson (), toString () sont différés à l'enfant, vous pouvez donc implémenter 'override' sur eux, et print() l'observable directement.
  890 +
  891 +class User {
  892 + String name, last;
  893 + int age;
  894 + User({this.name, this.last, this.age});
  895 +
  896 + @override
  897 + String toString() => '$name $last, $age ans';
  898 +}
  899 +
  900 +final user = User(name: 'John', last: 'Doe', age: 33).obs;
  901 +
  902 +// `user` est" réactif ", mais les propriétés à l'intérieur NE SONT PAS!
  903 +// Donc, si nous changeons une variable à l'intérieur ...
  904 +user.value.name = 'Roi';
  905 +// Le widget ne se reconstruira pas !,
  906 +// `Rx` n'a aucun indice lorsque vous changez quelque chose à l'intérieur de l'utilisateur.
  907 +// Donc, pour les classes personnalisées, nous devons "notifier" manuellement le changement.
  908 +user.refresh();
  909 +
  910 +// ou utiliser `update()`!
  911 +user.update((value){
  912 + value.name='Roi';
  913 +});
  914 +
  915 +print( user );
  916 +```
  917 +
  918 +#### GetView
  919 +
  920 +J'adore ce widget. Si simple, mais si utile!
  921 +
  922 +C'est un widget `const Stateless` qui a un getter` controller` pour un `Controller` enregistré, c'est tout.
  923 +
  924 +```dart
  925 + class AwesomeController extends GetxController {
  926 + final String title = 'My Awesome View';
  927 + }
  928 +
  929 + // N'oubliez PAS de passer le `Type` que vous avez utilisé pour enregistrer votre contrôleur!
  930 + class AwesomeView extends GetView<AwesomeController> {
  931 + @override
  932 + Widget build(BuildContext context) {
  933 + return Container(
  934 + padding: EdgeInsets.all(20),
  935 + child: Text(controller.title), // appelez `controller.quelqueChose`
  936 + );
  937 + }
  938 + }
  939 +```
  940 +
  941 +#### GetResponsiveView
  942 +
  943 +Étendez ce widget pour créer une vue réactive.
  944 +ce widget contient la propriété `screen` qui a toutes les
  945 +informations sur la taille et le type de l'écran.
  946 +
  947 +##### Guide d utilisation
  948 +
  949 +Vous avez deux options pour le créer:
  950 +
  951 +- avec la méthode `builder` vous renvoyez le widget à construire.
  952 +- 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.
  953 + Lorsque l'écran est [ScreenType.Tablet], la méthode `tablet` sera exécutée et ainsi de suite.
  954 + **Note:** Si vous utilisez cette méthode, veuillez définir la propriété `alwaysUseBuilder` à `false`
  955 +
  956 +Avec la propriété `settings`, vous pouvez définir la limite de largeur pour les types d'écran.
  957 +
  958 +![exemple](https://github.com/SchabanBo/get_page_example/blob/master/docs/Example.gif?raw=true)
  959 +Code pour cet écran
  960 +[code](https://github.com/SchabanBo/get_page_example/blob/master/lib/pages/responsive_example/responsive_view.dart)
  961 +
  962 +#### GetWidget
  963 +
  964 +La plupart des gens n'ont aucune idée de ce widget ou confondent totalement son utilisation.
  965 +Le cas d'utilisation est très rare, mais très spécifique: il `met en cache` un contrôleur.
  966 +En raison du _cache_, ne peut pas être un `const Stateless`.
  967 +
  968 +> Alors, quand avez-vous besoin de "mettre en cache" un contrôleur?
  969 +
  970 +Si vous utilisez, une autre fonctionnalité "pas si courante" de **GetX**: `Get.create()`.
  971 +
  972 +`Get.create(()=>Controller())` générera un nouveau `Controller` chaque fois que vous appelez
  973 +`Get.find<Controller>()`.
  974 +
  975 +C'est là que `GetWidget` brille ... comme vous pouvez l'utiliser, par exemple,
  976 +pour conserver une liste de <Todo>s. Donc, si le widget est "reconstruit", il conservera la même instance de contrôleur.
  977 +
  978 +#### GetxService
  979 +
  980 +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.
  981 +Il notifie simplement le **GetX** Dependency Injection system, que cette sous-classe
  982 +**ne peut pas** être supprimé de la mémoire.
  983 +
  984 +Donc est très utile pour garder vos "Services" toujours à portée de main et actifs avec `Get.find()`. Comme:
  985 +`ServiceAPI`, `ServiceDeSauvegarde`, `ServiceDeCaching`.
  986 +
  987 +```dart
  988 +Future<void> main() async {
  989 + await initServices(); /// Attend l'initialisation des services.
  990 + runApp(SomeApp());
  991 +}
  992 +
  993 +/// Est une démarche intelligente pour que vos services s'initialisent avant d'exécuter l'application Flutter.
  994 +/// car vous pouvez contrôler le flux d'exécution (peut-être devez-vous charger une configuration de thème,
  995 +/// apiKey, langue définie par l'utilisateur ... donc chargez SettingService avant d'exécuter ApiService.
  996 +/// donc GetMaterialApp () n'a pas besoin de se reconstruire et prend les valeurs directement.
  997 +void initServices() async {
  998 + print('starting services ...');
  999 + /// C'est ici que vous mettez get_storage, hive, shared_pref initialization.
  1000 + /// ou les connexions moor, ou autres choses async.
  1001 + await Get.putAsync(() => DbService().init());
  1002 + await Get.putAsync(SettingsService()).init();
  1003 + print('Tous les services ont démarré...');
  1004 +}
  1005 +
  1006 +class DbService extends GetxService {
  1007 + Future<DbService> init() async {
  1008 + print('$runtimeType retarde de 2 sec');
  1009 + await 2.delay();
  1010 + print('$runtimeType prêts!');
  1011 + return this;
  1012 + }
  1013 +}
  1014 +
  1015 +class SettingsService extends GetxService {
  1016 + void init() async {
  1017 + print("$runtimeType retarde d'1 sec");
  1018 + await 1.delay();
  1019 + print('$runtimeType prêts!');
  1020 + }
  1021 +}
  1022 +
  1023 +```
  1024 +
  1025 +La seule façon de supprimer réellement un `GetxService`, est d'utiliser` Get.reset () `qui est comme un
  1026 +"Hot Reboot" de votre application. N'oubliez donc pas que si vous avez besoin d'une persistance absolue d'une instance de classe
  1027 +durée de vie de votre application, utilisez `GetxService`.
  1028 +
  1029 +# Changements par rapport a 2.0
  1030 +
  1031 +1- Types Rx:
  1032 +
  1033 +| Avant | Après |
  1034 +| ------- | ---------- |
  1035 +| StringX | `RxString` |
  1036 +| IntX | `RxInt` |
  1037 +| MapX | `RxMap` |
  1038 +| ListX | `RxList` |
  1039 +| NumX | `RxNum` |
  1040 +| DoubleX | `RxDouble` |
  1041 +
  1042 +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é.
  1043 +
  1044 +
  1045 +2- NamedRoutes
  1046 +
  1047 +Avant:
  1048 +
  1049 +```dart
  1050 +GetMaterialApp(
  1051 + namedRoutes: {
  1052 + '/': GetRoute(page: Home()),
  1053 + }
  1054 +)
  1055 +```
  1056 +
  1057 +Maintenant:
  1058 +
  1059 +```dart
  1060 +GetMaterialApp(
  1061 + getPages: [
  1062 + GetPage(name: '/', page: () => Home()),
  1063 + ]
  1064 +)
  1065 +```
  1066 +
  1067 +Pourquoi ce changement?
  1068 +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.
  1069 +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:
  1070 +```dart
  1071 +
  1072 +GetStorage box = GetStorage();
  1073 +
  1074 +GetMaterialApp(
  1075 + getPages: [
  1076 + GetPage(name: '/', page:(){
  1077 + return box.hasData('token') ? Home() : Login();
  1078 + })
  1079 + ]
  1080 +)
  1081 +```
  1082 +
  1083 +# Pourquoi Getx?
  1084 +
  1085 +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.
  1086 +
  1087 +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.
  1088 +
  1089 +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.
  1090 +
  1091 +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`.
  1092 + 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.
  1093 + 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.
  1094 +
  1095 +
  1096 +# Communite
  1097 +
  1098 +## Chaines communautaires
  1099 +
  1100 +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.
  1101 +| **Slack** | **Discord** | **Telegram** |
  1102 +| :-------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
  1103 +| [![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) |
  1104 +
  1105 +## Comment contribuer
  1106 +
  1107 +_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)._
  1108 +
  1109 +- Aider à traduire les 'Readme's dans d'autres langues.
  1110 +- Ajout de documentation au readme (beaucoup de fonctions de Get n'ont pas encore été documentées).
  1111 +- 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).
  1112 +- Offrir des PRs pour code / tests.
  1113 +- Ajouter de nouvelles fonctions.
  1114 +
  1115 +Toute contribution est bienvenue!
  1116 +
  1117 +## Articles et videos
  1118 +
  1119 +- [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).
  1120 +- [Complete GetX™ Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI) - Route management video by Amateur Coder.
  1121 +- [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw) - State management video by Amateur Coder.
  1122 +- [GetX™ Other Features](https://youtu.be/ttQtlX_Q0eU) - Utils, storage, bindings and other features video by Amateur Coder.
  1123 +- [Firestore User with GetX | Todo App](https://www.youtube.com/watch?v=BiV0DcXgk58) - Video by Amateur Coder.
  1124 +- [Firebase Auth with GetX | Todo App](https://www.youtube.com/watch?v=-H-T_BSgfOE) - Video by Amateur Coder.
  1125 +- [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).
  1126 +- [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).
  1127 +- [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.
  1128 +- [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.
  1129 +- [GetX Flutter Firebase Auth Example](https://medium.com/@jeffmcmorris/getx-flutter-firebase-auth-example-b383c1dd1de2) - Article by Jeff McMorris.
  1130 +- [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter.
  1131 +- [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter.
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -**Bahasa: Indonesia (file ini), [Inggris](README.md), [Urdu](README.ur-PK.md), [China](README.zh-cn.md), [Portugis (Brazil)](README.pt-br.md), [Spanyol](README-es.md), [Russia](README.ru.md), [Polandia](README.pl.md), [Korea](README.ko-kr.md).** 3 +**Bahasa: Indonesia (file ini), [Inggris](README.md), [Urdu](README.ur-PK.md), [China](README.zh-cn.md), [Portugis (Brazil)](README.pt-br.md), [Spanyol](README-es.md), [Russia](README.ru.md), [Polandia](README.pl.md), [Korea](README.ko-kr.md), [French](README-fr.md)**
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score) 6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
@@ -148,7 +148,7 @@ class Home extends StatelessWidget { @@ -148,7 +148,7 @@ class Home extends StatelessWidget {
148 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))), 148 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
149 149
150 // Ganti 8 baris Navigator.push menggunan Get.to() agar lebih sederhana. Anda tidak perlu `context`. 150 // Ganti 8 baris Navigator.push menggunan Get.to() agar lebih sederhana. Anda tidak perlu `context`.
151 - body: Center(child: RaisedButton( 151 + body: Center(child: ElevatedButton(
152 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 152 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
153 floatingActionButton: 153 floatingActionButton:
154 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 154 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -**언어: [우르두어](README.ur-PK.md), [영어](README.md), [인도네시아 인](README.id-ID.md), [중국어](README.zh-cn.md), [브라질 포르투칼어](README.pt-br.md), [스페인어](README-es.md), [러시아어](README.ru.md), [폴란드어](README.pl.md), 한국어(이파일).** 3 +**언어: [우르두어](README.ur-PK.md), [영어](README.md), [인도네시아 인](README.id-ID.md), [중국어](README.zh-cn.md), [브라질 포르투칼어](README.pt-br.md), [스페인어](README-es.md), [러시아어](README.ru.md), [폴란드어](README.pl.md), 한국어(이파일), [French](README-fr.md)**
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score) 6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
@@ -16,9 +16,9 @@ @@ -16,9 +16,9 @@
16 16
17 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png) 17 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/getx.png)
18 18
19 -- [Get에 대하여](#Get에-대하여) 19 +- [Get에 대하여](#get에-대하여)
20 - [설치](#설치) 20 - [설치](#설치)
21 -- [GetX를 사용한 Counter 앱](#GetX를-사용한-Counter-앱) 21 +- [GetX를 사용한 Counter 앱](#getx를-사용한-counter-앱)
22 - [세가지 주요점](#세가지-주요점) 22 - [세가지 주요점](#세가지-주요점)
23 - [상태 관리](#상태-관리) 23 - [상태 관리](#상태-관리)
24 - [반응형 상태 관리자](#반응형-상태-관리자) 24 - [반응형 상태 관리자](#반응형-상태-관리자)
@@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
46 - [OnPageBuildStart](#onpagebuildstart) 46 - [OnPageBuildStart](#onpagebuildstart)
47 - [OnPageBuilt](#onpagebuilt) 47 - [OnPageBuilt](#onpagebuilt)
48 - [OnPageDispose](#onpagedispose) 48 - [OnPageDispose](#onpagedispose)
49 - - [기타 고급 API](#기타-고급-API) 49 + - [기타 고급 API](#기타-고급-api)
50 - [선택적 전역 설정과 수동 구성](#선택적-전역-설정과-수동-구성) 50 - [선택적 전역 설정과 수동 구성](#선택적-전역-설정과-수동-구성)
51 - [지역 상태 위젯들](#지역-상태-위젯들) 51 - [지역 상태 위젯들](#지역-상태-위젯들)
52 - [ValueBuilder](#valuebuilder) 52 - [ValueBuilder](#valuebuilder)
@@ -55,8 +55,8 @@ @@ -55,8 +55,8 @@
55 - [GetView](#getview) 55 - [GetView](#getview)
56 - [GetWidget](#getwidget) 56 - [GetWidget](#getwidget)
57 - [GetxService](#getxservice) 57 - [GetxService](#getxservice)
58 -- [2.0의 주요 변경점](#2.0의-주요-변경점)  
59 -- [왜-Getx인가?](#왜-Getx인가?) 58 +- [2.0의 주요 변경점](#20의-주요-변경점)
  59 +- [왜 Getx인가?](#왜-getx인가)
60 - [커뮤니티](#커뮤니티) 60 - [커뮤니티](#커뮤니티)
61 - [커뮤니티 채널](#커뮤니티-채널) 61 - [커뮤니티 채널](#커뮤니티-채널)
62 - [기여하는 방법](#기여하는-방법) 62 - [기여하는 방법](#기여하는-방법)
@@ -145,7 +145,7 @@ class Home extends StatelessWidget { @@ -145,7 +145,7 @@ class Home extends StatelessWidget {
145 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))), 145 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
146 146
147 // 8줄의 Navigator.push를 간단한 Get.to()로 변경합니다. context는 필요없습니다. 147 // 8줄의 Navigator.push를 간단한 Get.to()로 변경합니다. context는 필요없습니다.
148 - body: Center(child: RaisedButton( 148 + body: Center(child: ElevatedButton(
149 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 149 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
150 floatingActionButton: 150 floatingActionButton:
151 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 151 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -**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).** 3 +**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).**
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score) 6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
@@ -149,7 +149,7 @@ class Home extends StatelessWidget { @@ -149,7 +149,7 @@ class Home extends StatelessWidget {
149 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))), 149 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
150 150
151 // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context 151 // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
152 - body: Center(child: RaisedButton( 152 + body: Center(child: ElevatedButton(
153 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 153 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
154 floatingActionButton: 154 floatingActionButton:
155 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 155 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -*Languages: [English](README.md), [Indonezyjski](README.id-ID.md), [Urdu](README.ur-PK.md), [Język chiński](README.zh-cn.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md), [Russian](README.ru.md), Polish (Jesteś tu), [Koreański](README.ko-kr.md).* 3 +*Languages: [English](README.md), [Indonezyjski](README.id-ID.md), [Urdu](README.ur-PK.md), [Język chiński](README.zh-cn.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md), [Russian](README.ru.md), Polish (Jesteś tu), [Koreański](README.ko-kr.md), [French](README-fr.md)*
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg) 6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
@@ -113,7 +113,7 @@ class Home extends StatelessWidget { @@ -113,7 +113,7 @@ class Home extends StatelessWidget {
113 appBar: AppBar(title: Obx(() => Text("Clicks: " + c.count.string))), 113 appBar: AppBar(title: Obx(() => Text("Clicks: " + c.count.string))),
114 114
115 // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context 115 // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
116 - body: Center(child: RaisedButton( 116 + body: Center(child: ElevatedButton(
117 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 117 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
118 floatingActionButton: 118 floatingActionButton:
119 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 119 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -**Idiomas: [Inglês](README.md), [Indonésia](README.id-ID.md), [Urdu](README.ur-PK.md), [Chinês](README.zh-cn.md), Português Brasileiro (este arquivo), [Espanhol](README-es.md), [Russo](README.ru.md), [Polonês](README.pl.md), [Coreana](README.ko-kr.md).** 3 +**Idiomas: [Inglês](README.md), [Indonésia](README.id-ID.md), [Urdu](README.ur-PK.md), [Chinês](README.zh-cn.md), Português (este arquivo), [Espanhol](README-es.md), [Russo](README.ru.md), [Polonês](README.pl.md), [Coreano](README.ko-kr.md), [Francês](README-fr.md)**
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score) 6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
@@ -158,7 +158,7 @@ class Home extends StatelessWidget { @@ -158,7 +158,7 @@ class Home extends StatelessWidget {
158 appBar: AppBar(title: Obx(() => Text("Total de cliques: ${c.count}"))), 158 appBar: AppBar(title: Obx(() => Text("Total de cliques: ${c.count}"))),
159 159
160 // Troque o Navigator.push de 8 linhas por um simples Get.to(). Você não precisa do 'context' 160 // Troque o Navigator.push de 8 linhas por um simples Get.to(). Você não precisa do 'context'
161 - body: Center(child: RaisedButton( 161 + body: Center(child: ElevatedButton(
162 child: Text("Ir pra Outra tela"), onPressed: () => Get.to(Outra()))), 162 child: Text("Ir pra Outra tela"), onPressed: () => Get.to(Outra()))),
163 floatingActionButton: 163 floatingActionButton:
164 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 164 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -_Языки: Русский (этот файл), [индонезийский](README.id-ID.md), [урду](README.ur-PK.md), [Английский](README.md), [Китайский](README.zh-cn.md), [Бразильский Португальский](README.pt-br.md), [Испанский](README-es.md), [Польский](README.pl.md), [Kорейский](README.ko-kr.md)._ 3 +_Языки: Русский (этот файл), [индонезийский](README.id-ID.md), [урду](README.ur-PK.md), [Английский](README.md), [Китайский](README.zh-cn.md), [Бразильский Португальский](README.pt-br.md), [Испанский](README-es.md), [Польский](README.pl.md), [Kорейский](README.ko-kr.md), [French](README-fr.md)._
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg) 6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
@@ -29,14 +29,14 @@ _Языки: Русский (этот файл), [индонезийский](RE @@ -29,14 +29,14 @@ _Языки: Русский (этот файл), [индонезийский](RE
29 - [Утилиты](#утилиты) 29 - [Утилиты](#утилиты)
30 - [Интернационализация](#интернационализация) 30 - [Интернационализация](#интернационализация)
31 - [Переводы](#переводы) 31 - [Переводы](#переводы)
32 - - [Применение переводов](#применение-переводов) 32 + - [Использование переводов](#использование-переводов)
33 - [Локализация](#локализация) 33 - [Локализация](#локализация)
34 - [Изменение локализации](#изменение-локализации) 34 - [Изменение локализации](#изменение-локализации)
35 - - [Системная локализация](#системная-локализации) 35 + - [Системная локализация](#системная-локализация)
36 - [Изменение темы](#изменение-темы) 36 - [Изменение темы](#изменение-темы)
37 - [Другие API](#другие-api) 37 - [Другие API](#другие-api)
38 - [Дополнительные глобальные настройки и ручные настройки](#дополнительные-глобальные-настройки-и-ручные-настройки) 38 - [Дополнительные глобальные настройки и ручные настройки](#дополнительные-глобальные-настройки-и-ручные-настройки)
39 - - [Локальные виджеты состояния](#локальные-виджеты-состояний) 39 + - [Локальные виджеты состояния](#локальные-виджеты-состояния)
40 - [ValueBuilder](#valuebuilder) 40 - [ValueBuilder](#valuebuilder)
41 - [ObxValue](#obxvalue) 41 - [ObxValue](#obxvalue)
42 - [Полезные советы](#полезные-советы) 42 - [Полезные советы](#полезные-советы)
@@ -45,7 +45,7 @@ _Языки: Русский (этот файл), [индонезийский](RE @@ -45,7 +45,7 @@ _Языки: Русский (этот файл), [индонезийский](RE
45 - [GetxService](#getxservice) 45 - [GetxService](#getxservice)
46 - [Критические изменения по сравнению с версией 2.0](#критические-изменения-по-сравнению-с-версией-20) 46 - [Критические изменения по сравнению с версией 2.0](#критические-изменения-по-сравнению-с-версией-20)
47 - [Почему Getx?](#почему-getx) 47 - [Почему Getx?](#почему-getx)
48 -- [Сообщество](#сообщество) 48 +- [Сообщества](#сообщества)
49 - [Каналы сообщества](#каналы-сообщества) 49 - [Каналы сообщества](#каналы-сообщества)
50 - [Как внести свой вклад](#как-внести-свой-вклад) 50 - [Как внести свой вклад](#как-внести-свой-вклад)
51 - [Статьи и видео](#статьи-и-видео) 51 - [Статьи и видео](#статьи-и-видео)
@@ -129,7 +129,7 @@ class Home extends StatelessWidget { @@ -129,7 +129,7 @@ class Home extends StatelessWidget {
129 appBar: AppBar(title: Obx(() => Text("Кликов: ${c.count}"))), 129 appBar: AppBar(title: Obx(() => Text("Кликов: ${c.count}"))),
130 130
131 // Замените 8 строк Navigator.push простым Get.to(). Вам не нужен context! 131 // Замените 8 строк Navigator.push простым Get.to(). Вам не нужен context!
132 - body: Center(child: RaisedButton( 132 + body: Center(child: ElevatedButton(
133 child: Text("Перейти к Other"), onPressed: () => Get.to(Other()))), 133 child: Text("Перейти к Other"), onPressed: () => Get.to(Other()))),
134 floatingActionButton: 134 floatingActionButton:
135 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 135 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -**🌎 اردو ( Selected ✔) [| انگریزی |](README.md) [| انڈونیشی |](README.id-ID.md) [چینی |](README.zh-cn.md) [برازیلی پرتگالی |](README.pt-br.md) [ہسپانوی |](README-es.md) [روسی |](README.ru.md) [پولش |](README.pl.md) [کورین |](README.ko-kr.md)** 3 +**🌎 اردو ( Selected ✔) [| انگریزی |](README.md) [| انڈونیشی |](README.id-ID.md) [چینی |](README.zh-cn.md) [برازیلی پرتگالی |](README.pt-br.md) [ہسپانوی |](README-es.md) [روسی |](README.ru.md) [پولش |](README.pl.md) [کورین |](README.ko-kr.md), [French](README-fr.md)**
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score) 6 [![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
@@ -42,11 +42,13 @@ @@ -42,11 +42,13 @@
42 - [ترجیح](#ترجیح) 42 - [ترجیح](#ترجیح)
43 - [ری ڈائریکٹ](#ری-ڈائریکٹ) 43 - [ری ڈائریکٹ](#ری-ڈائریکٹ)
44 - [جب پیج کی درخواست کی جائے](#جب-پیج-کی-درخواست-کی-جائے) 44 - [جب پیج کی درخواست کی جائے](#جب-پیج-کی-درخواست-کی-جائے)
  45 + - [آنبائنڈنگ اسٹارٹ](#آنبائنڈنگ-اسٹارٹ)
  46 + - [آنپیج بلڈ اسٹارٹ](#آنپیج-بلڈ-اسٹارٹ)
45 - [جب پیج لوڈ ہو](#جب-پیج-لوڈ-ہو) 47 - [جب پیج لوڈ ہو](#جب-پیج-لوڈ-ہو)
46 - [جب صفحہ تصرف ہوجائے](#جب-صفحہ-تصرف-ہوجائے) 48 - [جب صفحہ تصرف ہوجائے](#جب-صفحہ-تصرف-ہوجائے)
47 - - [دوسرے اعلی درجے کی APIs](#دوسرے-اعلی-درجے-کی-APIs) 49 + - [دوسرے اعلی درجے کی APIs](#دوسرے-اعلی-درجے-کی-apis)
48 - [اختیاری عالمی ترتیبات اور دستی تشکیلات](#اختیاری-عالمی-ترتیبات-اور-دستی-تشکیلات) 50 - [اختیاری عالمی ترتیبات اور دستی تشکیلات](#اختیاری-عالمی-ترتیبات-اور-دستی-تشکیلات)
49 - - [مقامی اسٹیٹ ویجٹ](#مقامی-اسٹیٹ-ویجٹ) - 51 + - [مقامی اسٹیٹ ویجٹ](#مقامی-اسٹیٹ-ویجٹ)
50 - [ویلیو بلڈر](#ویلیو-بلڈر) 52 - [ویلیو بلڈر](#ویلیو-بلڈر)
51 - [اوبکس ویلیو](#اوبکس-ویلیو) 53 - [اوبکس ویلیو](#اوبکس-ویلیو)
52 - [کارآمد نکات](#کارآمد-نکات) 54 - [کارآمد نکات](#کارآمد-نکات)
@@ -54,7 +56,7 @@ @@ -54,7 +56,7 @@
54 - [گیٹ ویجٹ](#گیٹ-ویجٹ) 56 - [گیٹ ویجٹ](#گیٹ-ویجٹ)
55 - [گیٹکس سروس](#گیٹکس-سروس) 57 - [گیٹکس سروس](#گیٹکس-سروس)
56 - [پچھلے ورژن سے اہم تبدیلیاں](#پچھلے-ورژن-سے-اہم-تبدیلیاں) 58 - [پچھلے ورژن سے اہم تبدیلیاں](#پچھلے-ورژن-سے-اہم-تبدیلیاں)
57 -- [گیٹکس کیوں؟](#گیٹکس-کیوں؟) 59 +- [گیٹکس کیوں؟](#گیٹکس-کیوں)
58 - [سماجی خدمات](#سماجی-خدمات) 60 - [سماجی خدمات](#سماجی-خدمات)
59 - [کمیونٹی چینلز](#کمیونٹی-چینلز) 61 - [کمیونٹی چینلز](#کمیونٹی-چینلز)
60 - [کس طرح شراکت کریں](#کس-طرح-شراکت-کریں) 62 - [کس طرح شراکت کریں](#کس-طرح-شراکت-کریں)
@@ -135,7 +137,7 @@ class Home extends StatelessWidget { @@ -135,7 +137,7 @@ class Home extends StatelessWidget {
135 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))), 137 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
136 138
137 // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context 139 // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
138 - body: Center(child: RaisedButton( 140 + body: Center(child: ElevatedButton(
139 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 141 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
140 floatingActionButton: 142 floatingActionButton:
141 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 143 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png) 1 ![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
2 2
3 -_语言: 中文, [英文](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)._ 3 +_语言: 中文, [英文](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), [French](README-fr.md)._
4 4
5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get) 5 [![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg) 6 ![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
@@ -67,8 +67,13 @@ _霂剛: 銝剜, [(README.md), [摨血側镼蹂(README.id-ID.md), [銋 @@ -67,8 +67,13 @@ _霂剛: 銝剜, [(README.md), [摨血側镼蹂(README.id-ID.md), [銋
67 67
68 **此外,通过[Get CLI](https://github.com/jonataslaw/get_cli)**,无论是在服务器上还是在前端,整个开发过程都可以完全自动化。 68 **此外,通过[Get CLI](https://github.com/jonataslaw/get_cli)**,无论是在服务器上还是在前端,整个开发过程都可以完全自动化。
69 69
70 -**此外,为了进一步提高您的生产效率,我们还为您准备了  
71 -[VSCode扩展](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets)[Android Studio/Intellij扩展](https://plugins.jetbrains.com/plugin/14975-getx-snippets)** 70 +**此外,为了进一步提高您的生产效率,我们还为您准备了一些插件**
  71 +
  72 +- **getx_template**:一键生成每个页面必需的文件夹、文件、模板代码等等
  73 + - [Android Studio/Intellij插件](https://plugins.jetbrains.com/plugin/15919-getx)
  74 +- **GetX Snippets**:输入少量字母,自动提示选择后,可生成常用的模板代码
  75 + - [Android Studio/Intellij扩展](https://plugins.jetbrains.com/plugin/14975-getx-snippets)
  76 + - [VSCode扩展](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets)
72 77
73 # 安装 78 # 安装
74 79
@@ -133,7 +138,7 @@ class Home extends StatelessWidget { @@ -133,7 +138,7 @@ class Home extends StatelessWidget {
133 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))), 138 appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
134 139
135 // 用一个简单的Get.to()即可代替Navigator.push那8行,无需上下文! 140 // 用一个简单的Get.to()即可代替Navigator.push那8行,无需上下文!
136 - body: Center(child: RaisedButton( 141 + body: Center(child: ElevatedButton(
137 child: Text("Go to Other"), onPressed: () => Get.to(Other()))), 142 child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
138 floatingActionButton: 143 floatingActionButton:
139 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment)); 144 FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
@@ -209,7 +214,7 @@ Obx(() => Text("${controller.name}")); @@ -209,7 +214,7 @@ Obx(() => Text("${controller.name}"));
209 214
210 ### 关于状态管理的更多细节 215 ### 关于状态管理的更多细节
211 216
212 -**关于状态管理更深入的解释请查看[这里](./documentation/zh_CN/state_management.md)。在那里你将看到更多的例子,以及简单的阶段管理器和响应式状态管理器之间的区别** 217 +**关于状态管理更深入的解释请查看[这里](./documentation/zh_CN/state_management.md)。在那里你将看到更多的例子,以及简单的状态管理器和响应式状态管理器之间的区别**
213 218
214 你会对GetX的能力有一个很好的了解。 219 你会对GetX的能力有一个很好的了解。
215 220
@@ -906,4 +911,6 @@ _銝粹★插賑撠鞊芸撘箄賑 @@ -906,4 +911,6 @@ _銝粹★插賑撠鞊芸撘箄賑
906 - [GetX Flutter Firebase Auth Example](https://medium.com/@jeffmcmorris/getx-flutter-firebase-auth-example-b383c1dd1de2) - Article by Jeff McMorris. 911 - [GetX Flutter Firebase Auth Example](https://medium.com/@jeffmcmorris/getx-flutter-firebase-auth-example-b383c1dd1de2) - Article by Jeff McMorris.
907 - [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter. 912 - [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter.
908 - [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter. 913 - [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter.
  914 +- [Flutter GetX use --- simple charm!](https://github.com/CNAD666/getx_template/blob/main/docs/Use%20of%20Flutter%20GetX---simple%20charm!.md) - CNAD666
  915 + - [Flutter GetX使用---简洁的魅力!](https://juejin.cn/post/6924104248275763208)
909 916
@@ -20,6 +20,8 @@ linter: @@ -20,6 +20,8 @@ linter:
20 # INCLUDE_FIX (copy of effective dart 1.2.0) 20 # INCLUDE_FIX (copy of effective dart 1.2.0)
21 # STYLE 21 # STYLE
22 camel_case_types: true 22 camel_case_types: true
  23 + close_sinks: true
  24 + unnecessary_statements: true
23 camel_case_extensions: true 25 camel_case_extensions: true
24 library_names: true 26 library_names: true
25 file_names: true 27 file_names: true
@@ -246,6 +246,28 @@ print(Get.parameters['user']); @@ -246,6 +246,28 @@ print(Get.parameters['user']);
246 // out: 34954 246 // out: 34954
247 ``` 247 ```
248 248
  249 +or send multiple parameters like this
  250 +
  251 +```dart
  252 +Get.toNamed("/profile/34954?flag=true&country=italy");
  253 +```
  254 +or
  255 +```dart
  256 +var parameters = <String, String>{"flag": "true","country": "italy",};
  257 +Get.toNamed("/profile/34954", parameters: parameters);
  258 +```
  259 +
  260 +On second screen take the data by parameters as usually
  261 +
  262 +```dart
  263 +print(Get.parameters['user']);
  264 +print(Get.parameters['flag']);
  265 +print(Get.parameters['country']);
  266 +// out: 34954 true italy
  267 +```
  268 +
  269 +
  270 +
249 And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (you can call your routes directly from your BLoC or Controller class), and when your app is compiled to the web, your routes will appear in the url <3 271 And now, all you need to do is use Get.toNamed() to navigate your named routes, without any context (you can call your routes directly from your BLoC or Controller class), and when your app is compiled to the web, your routes will appear in the url <3
250 272
251 ### Middleware 273 ### Middleware
@@ -313,7 +335,7 @@ class First extends StatelessWidget { @@ -313,7 +335,7 @@ class First extends StatelessWidget {
313 title: Text('First Route'), 335 title: Text('First Route'),
314 ), 336 ),
315 body: Center( 337 body: Center(
316 - child: RaisedButton( 338 + child: ElevatedButton(
317 child: Text('Open route'), 339 child: Text('Open route'),
318 onPressed: () { 340 onPressed: () {
319 Get.toNamed("/second"); 341 Get.toNamed("/second");
@@ -338,7 +360,7 @@ class Second extends StatelessWidget { @@ -338,7 +360,7 @@ class Second extends StatelessWidget {
338 title: Text('second Route'), 360 title: Text('second Route'),
339 ), 361 ),
340 body: Center( 362 body: Center(
341 - child: RaisedButton( 363 + child: ElevatedButton(
342 child: Text('Open route'), 364 child: Text('Open route'),
343 onPressed: () { 365 onPressed: () {
344 Get.toNamed("/third"); 366 Get.toNamed("/third");
@@ -357,7 +379,7 @@ class Third extends StatelessWidget { @@ -357,7 +379,7 @@ class Third extends StatelessWidget {
357 title: Text("Third Route"), 379 title: Text("Third Route"),
358 ), 380 ),
359 body: Center( 381 body: Center(
360 - child: RaisedButton( 382 + child: ElevatedButton(
361 onPressed: () { 383 onPressed: () {
362 Get.back(); 384 Get.back();
363 }, 385 },
@@ -428,7 +450,7 @@ Get.snackbar( @@ -428,7 +450,7 @@ Get.snackbar(
428 // Color leftBarIndicatorColor, 450 // Color leftBarIndicatorColor,
429 // List<BoxShadow> boxShadows, 451 // List<BoxShadow> boxShadows,
430 // Gradient backgroundGradient, 452 // Gradient backgroundGradient,
431 - // FlatButton mainButton, 453 + // TextButton mainButton,
432 // OnTap onTap, 454 // OnTap onTap,
433 // bool isDismissible, 455 // bool isDismissible,
434 // bool showProgressIndicator, 456 // bool showProgressIndicator,
@@ -518,7 +540,7 @@ Navigator( @@ -518,7 +540,7 @@ Navigator(
518 title: Text("Main"), 540 title: Text("Main"),
519 ), 541 ),
520 body: Center( 542 body: Center(
521 - child: FlatButton( 543 + child: TextButton(
522 color: Colors.blue, 544 color: Colors.blue,
523 onPressed: () { 545 onPressed: () {
524 Get.toNamed('/second', id:1); // navigate by your nested route by index 546 Get.toNamed('/second', id:1); // navigate by your nested route by index
@@ -242,7 +242,21 @@ Y en la segunda pantalla tome los datos por parámetro @@ -242,7 +242,21 @@ Y en la segunda pantalla tome los datos por parámetro
242 242
243 ```dart 243 ```dart
244 print(Get.parameters['user']); 244 print(Get.parameters['user']);
245 -// out: 34954 245 +// salida: 34954
  246 +```
  247 +
  248 +o envie multiples parametros de la siguiente manera
  249 +
  250 +```dart
  251 +Get.toNamed("/profile/34954?flag=true");
  252 +```
  253 +
  254 +En la segunda pantalla tome los parametros como lo haria normalmente
  255 +
  256 +```dart
  257 +print(Get.parameters['user']);
  258 +print(Get.parameters['flag']);
  259 +// salida: 34954 true
246 ``` 260 ```
247 261
248 Y ahora, todo lo que necesita hacer es usar Get.toNamed() para navegar por sus rutas nombradas, sin ningún contexto (puede llamar a sus rutas directamente desde su clase BLoC o Controller), y cuando su aplicación se compila para web, sus rutas aparecerán en la url del navegador <3 262 Y ahora, todo lo que necesita hacer es usar Get.toNamed() para navegar por sus rutas nombradas, sin ningún contexto (puede llamar a sus rutas directamente desde su clase BLoC o Controller), y cuando su aplicación se compila para web, sus rutas aparecerán en la url del navegador <3
@@ -312,7 +326,7 @@ class First extends StatelessWidget { @@ -312,7 +326,7 @@ class First extends StatelessWidget {
312 title: Text('First Route'), 326 title: Text('First Route'),
313 ), 327 ),
314 body: Center( 328 body: Center(
315 - child: RaisedButton( 329 + child: ElevatedButton(
316 child: Text('Open route'), 330 child: Text('Open route'),
317 onPressed: () { 331 onPressed: () {
318 Get.toNamed("/second"); 332 Get.toNamed("/second");
@@ -337,7 +351,7 @@ class Second extends StatelessWidget { @@ -337,7 +351,7 @@ class Second extends StatelessWidget {
337 title: Text('second Route'), 351 title: Text('second Route'),
338 ), 352 ),
339 body: Center( 353 body: Center(
340 - child: RaisedButton( 354 + child: ElevatedButton(
341 child: Text('Open route'), 355 child: Text('Open route'),
342 onPressed: () { 356 onPressed: () {
343 Get.toNamed("/third"); 357 Get.toNamed("/third");
@@ -356,7 +370,7 @@ class Third extends StatelessWidget { @@ -356,7 +370,7 @@ class Third extends StatelessWidget {
356 title: Text("Third Route"), 370 title: Text("Third Route"),
357 ), 371 ),
358 body: Center( 372 body: Center(
359 - child: RaisedButton( 373 + child: ElevatedButton(
360 onPressed: () { 374 onPressed: () {
361 Get.back(); 375 Get.back();
362 }, 376 },
@@ -427,7 +441,7 @@ Get.snackbar( @@ -427,7 +441,7 @@ Get.snackbar(
427 // Color leftBarIndicatorColor, 441 // Color leftBarIndicatorColor,
428 // List<BoxShadow> boxShadows, 442 // List<BoxShadow> boxShadows,
429 // Gradient backgroundGradient, 443 // Gradient backgroundGradient,
430 - // FlatButton mainButton, 444 + // TextButton mainButton,
431 // OnTap onTap, 445 // OnTap onTap,
432 // bool isDismissible, 446 // bool isDismissible,
433 // bool showProgressIndicator, 447 // bool showProgressIndicator,
@@ -519,7 +533,7 @@ Navigator( @@ -519,7 +533,7 @@ Navigator(
519 title: Text("Main"), 533 title: Text("Main"),
520 ), 534 ),
521 body: Center( 535 body: Center(
522 - child: FlatButton( 536 + child: TextButton(
523 color: Colors.blue, 537 color: Colors.blue,
524 onPressed: () { 538 onPressed: () {
525 Get.toNamed('/second', id:1); // navigate by your nested route by index 539 Get.toNamed('/second', id:1); // navigate by your nested route by index
  1 +# Gestion des dépendances
  2 +- [Gestion des dépendances](#Gestion-des-dépendances)
  3 + - [Instanciation des methodes](#Instanciation-des-methodes)
  4 + - [Get.put()](#getput)
  5 + - [Get.lazyPut](#getlazyput)
  6 + - [Get.putAsync](#getputasync)
  7 + - [Get.create](#getcreate)
  8 + - [Utilisation de méthodes/classes instanciées](#utilisation-de-mthodes-classes-instancies)
  9 + - [Différences entre les méthodes](#differences-entre-les-methodes)
  10 + - [Bindings](#bindings)
  11 + - [Classe Bindings](#classe-bindings)
  12 + - [BindingsBuilder](#bindingsbuilder)
  13 + - [SmartManagement](#smartmanagement)
  14 + - [Comment changer](#comment-changer)
  15 + - [SmartManagement.full](#smartmanagementfull)
  16 + - [SmartManagement.onlyBuilders](#smartmanagementonlybuilders)
  17 + - [SmartManagement.keepFactory](#smartmanagementkeepfactory)
  18 + - [Comment Bindings fonctionne sous le capot](#comment-bindings-fonctionne-sous-le-capot)
  19 + - [Notes](#notes)
  20 +
  21 +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:
  22 +
  23 +```dart
  24 +Controller controller = Get.put(Controller()); // Au lieu de Controller controller = Controller();
  25 +```
  26 +
  27 +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.
  28 +Vous pouvez donc utiliser votre contrôleur (ou classe Bloc) normalement
  29 +
  30 +- 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.
  31 +- 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.
  32 +
  33 +## Instanciation des methodes
  34 +Les méthodes et leurs paramètres configurables sont:
  35 +
  36 +### Get.put()
  37 +
  38 +La manière la plus courante d'insérer une dépendance. Bon pour les contrôleurs de vos vues par exemple.
  39 +
  40 +```dart
  41 +Get.put<SomeClass>(SomeClass());
  42 +Get.put<LoginController>(LoginController(), permanent: true);
  43 +Get.put<ListItemController>(ListItemController, tag: "un String unique");
  44 +```
  45 +
  46 +Ce sont toutes les options que vous pouvez définir lorsque vous utilisez put:
  47 +```dart
  48 +Get.put<S>(
  49 + // obligatoire: la classe que vous voulez que get enregistre, comme un 'controler' ou autre
  50 + // note: "S" signifie que ca peut etre une classe de n'importe quel type
  51 + S dependency
  52 +
  53 + // optionnel: c'est pour quand vous voulez plusieurs classes qui sont du même type
  54 + // puisque vous obtenez normalement une classe en utilisant Get.find<Controller>(),
  55 + // vous devez utiliser ce tag pour indiquer de quelle instance vous avez besoin
  56 + // doit être un String unique
  57 + String tag,
  58 +
  59 + // optionnel: par défaut, get supprimera les instances une fois qu'elles ne seront plus utilisées (exemple,
  60 + // le contrôleur d'une vue qui est fermée), mais vous pourriez avoir besoin que l'instance
  61 + // soit conservée dans toute l'application, comme une instance de sharedPreferences ou quelque chose du genre
  62 + // donc vous utilisez ceci
  63 + // équivaut à false par défaut
  64 + bool permanent = false,
  65 +
  66 + // facultatif: permet après avoir utilisé une classe abstraite dans un test, de la remplacer par une autre et de suivre le test.
  67 + // équivaut à false par défaut
  68 + bool overrideAbstract = false,
  69 +
  70 + // facultatif: vous permet de créer la dépendance en utilisant la fonction au lieu de la dépendance elle-même.
  71 + // ce n'est pas couramment utilisé
  72 + InstanceBuilderCallback<S> builder,
  73 +)
  74 +```
  75 +
  76 +### Get.lazyPut
  77 +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à.
  78 +
  79 +```dart
  80 +/// ApiMock ne sera appelé que lorsque quelqu'un utilise Get.find <ApiMock> pour la première fois
  81 +Get.lazyPut<ApiMock>(() => ApiMock());
  82 +
  83 +Get.lazyPut<FirebaseAuth>(
  84 + () {
  85 + // ... some logic if needed
  86 + return FirebaseAuth();
  87 + },
  88 + tag: Math.random().toString(),
  89 + fenix: true
  90 +)
  91 +
  92 +Get.lazyPut<Controller>(() => Controller() )
  93 +```
  94 +
  95 +Ce sont toutes les options que vous pouvez définir lors de l'utilisation de lazyPut:
  96 +```dart
  97 +Get.lazyPut<S>(
  98 + // obligatoire: une méthode qui sera exécutée lorsque votre classe sera appelée pour la première fois
  99 + InstanceBuilderCallback builder,
  100 +
  101 + // facultatif: identique à Get.put(), il est utilisé lorsque vous voulez plusieurs instances différentes d'une même classe
  102 + // doit être unique
  103 + String tag,
  104 +
  105 + // facultatif: cela est similaire à "permanent", la différence est que l'instance est supprimée lorsqu'elle
  106 + // n'est pas utilisée, mais lorsqu'elle est à nouveau nécessaire, Get recrée l'instance
  107 + // identique à "SmartManagement.keepFactory" dans l'API Bindings
  108 + // vaut false par défaut
  109 + bool fenix = false
  110 +
  111 +)
  112 +```
  113 +
  114 +### Get.putAsync
  115 +Si vous souhaitez enregistrer une instance async, vous pouvez utiliser `Get.putAsync`:
  116 +
  117 +```dart
  118 +Get.putAsync<SharedPreferences>(() async {
  119 + final prefs = await SharedPreferences.getInstance();
  120 + await prefs.setInt('counter', 12345);
  121 + return prefs;
  122 +});
  123 +
  124 +Get.putAsync<YourAsyncClass>(() async => await YourAsyncClass())
  125 +```
  126 +
  127 +Ce sont toutes les options que vous pouvez définir lors de l'utilisation de putAsync:
  128 +```dart
  129 +Get.putAsync<S>(
  130 +
  131 + // obligatoire: une méthode async qui sera exécutée pour instancier votre classe
  132 + AsyncInstanceBuilderCallback<S> builder,
  133 +
  134 + // facultatif: identique à Get.put(), il est utilisé lorsque vous voulez plusieurs instances différentes d'une même classe
  135 + // doit être unique
  136 + String tag,
  137 +
  138 + // facultatif: identique à Get.put(), utilisé lorsque vous devez maintenir cette instance active dans l'ensemble de l'application
  139 + // vaut false par défaut
  140 + bool permanent = false
  141 +)
  142 +```
  143 +
  144 +### Get.create
  145 +
  146 +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).
  147 +
  148 +```dart
  149 +Get.Create<SomeClass>(() => SomeClass());
  150 +Get.Create<LoginController>(() => LoginController());
  151 +```
  152 +
  153 +Ce sont toutes les options que vous pouvez définir lors de l'utilisation de create:
  154 +
  155 +```dart
  156 +Get.create<S>(
  157 + // requis: une fonction qui renvoie une classe qui sera "fabriquée" chaque
  158 + // fois que `Get.find()` est appelé
  159 + // Exemple: Get.create<YourClass>(() => YourClass())
  160 + FcBuilderFunc<S> builder,
  161 +
  162 + // facultatif: comme Get.put(), mais il est utilisé lorsque vous avez besoin de plusieurs instances
  163 + // d'une même classe
  164 + // Utile dans le cas où vous avez une liste oú chaque élément a besoin de son propre contrôleur
  165 + // doit être une String unique. Changez simplement de 'tag' en 'name'
  166 + String name,
  167 +
  168 + // optionnel: tout comme dans `Get.put()`, c'est pour quand vous devez garder l'
  169 + // instance vivante dans toute l'application. La différence est que dans Get.create,
  170 + // permanent est 'true' par défaut
  171 + bool permanent = true
  172 +```
  173 +
  174 +## Utilisation de méthodes/classes instanciées
  175 +
  176 +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:
  177 +
  178 +```dart
  179 +final controller = Get.find<Controller>();
  180 +// OR
  181 +Controller controller = Get.find();
  182 +
  183 +// Oui, cela ressemble à Magic, Get trouvera votre contrôleur et vous le livrera.
  184 +// Vous pouvez avoir 1 million de contrôleurs instanciés, Get vous trouvera toujours le bon contrôleur.
  185 +```
  186 +
  187 +Et puis vous pourrez récupérer les données de votre contrôleur qui ont été obtenues là-bas:
  188 +
  189 +```dart
  190 +Text(controller.textFromApi);
  191 +```
  192 +
  193 +La valeur renvoyée étant une classe normale, vous pouvez faire tout ce que vous voulez:
  194 +```dart
  195 +int count = Get.find<SharedPreferences>().getInt('counter');
  196 +print(count); // donne: 12345
  197 +```
  198 +
  199 +Pour supprimer une instance de Get:
  200 +
  201 +```dart
  202 +Get.delete<Controller>(); //généralement, vous n'avez pas besoin de le faire car GetX supprime déjà les contrôleurs inutilisés-
  203 +```
  204 +
  205 +## Differences entre les methodes
  206 +
  207 +Commençons par le `fenix` de Get.lazyPut et le `permanent` des autres méthodes.
  208 +
  209 +La différence fondamentale entre `permanent` et `fenix` réside dans la manière dont vous souhaitez stocker vos instances.
  210 +
  211 +Renforcement: par défaut, GetX supprime les instances lorsqu'elles ne sont pas utilisées.
  212 +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é.
  213 +
  214 +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.
  215 +
  216 +`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.
  217 +
  218 +Différences entre les méthodes:
  219 +
  220 +- 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.
  221 +
  222 +- 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.
  223 +
  224 +- 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.
  225 +
  226 +## Bindings
  227 +
  228 +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.
  229 +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.
  230 +Dans la version 2.10, Get a complètement implémenté l'API Bindings.
  231 +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.
  232 +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.
  233 +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.
  234 +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.
  235 +
  236 +### Classe Bindings
  237 +
  238 +- Créer une classe et implémenter Bindings
  239 +
  240 +```dart
  241 +class HomeBinding implements Bindings {}
  242 +```
  243 +
  244 +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:
  245 +
  246 +```dart
  247 +class HomeBinding implements Bindings {
  248 + @override
  249 + void dependencies() {
  250 + Get.lazyPut<HomeController>(() => HomeController());
  251 + Get.put<Service>(()=> Api());
  252 + }
  253 +}
  254 +
  255 +class DetailsBinding implements Bindings {
  256 + @override
  257 + void dependencies() {
  258 + Get.lazyPut<DetailsController>(() => DetailsController());
  259 + }
  260 +}
  261 +```
  262 +
  263 +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.
  264 +
  265 +- En utilisant les routes nommées:
  266 +
  267 +```dart
  268 +getPages: [
  269 + GetPage(
  270 + name: '/',
  271 + page: () => HomeView(),
  272 + binding: HomeBinding(),
  273 + ),
  274 + GetPage(
  275 + name: '/details',
  276 + page: () => DetailsView(),
  277 + binding: DetailsBinding(),
  278 + ),
  279 +];
  280 +```
  281 +
  282 +- En utilisant les routes normales:
  283 +
  284 +```dart
  285 +Get.to(Home(), binding: HomeBinding());
  286 +Get.to(DetailsView(), binding: DetailsBinding())
  287 +```
  288 +
  289 +Là, vous n'avez plus à vous soucier de la gestion de la mémoire de votre application, Get le fera pour vous.
  290 +
  291 +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.
  292 +
  293 +```dart
  294 +GetMaterialApp(
  295 + initialBinding: SampleBind(),
  296 + home: Home(),
  297 +);
  298 +```
  299 +
  300 +### BindingsBuilder
  301 +
  302 +La manière par défaut de créer un binding est de créer une classe qui implémente Bindings.
  303 +
  304 +Mais alternativement, vous pouvez utiliser le callback `BindingsBuilder` afin de pouvoir simplement utiliser une fonction pour instancier ce que vous désirez.
  305 +
  306 +Exemple:
  307 +
  308 +```dart
  309 +getPages: [
  310 + GetPage(
  311 + name: '/',
  312 + page: () => HomeView(),
  313 + binding: BindingsBuilder(() {
  314 + Get.lazyPut<ControllerX>(() => ControllerX());
  315 + Get.put<Service>(()=> Api());
  316 + }),
  317 + ),
  318 + GetPage(
  319 + name: '/details',
  320 + page: () => DetailsView(),
  321 + binding: BindingsBuilder(() {
  322 + Get.lazyPut<DetailsController>(() => DetailsController());
  323 + }),
  324 + ),
  325 +];
  326 +```
  327 +
  328 +De cette façon, vous pouvez éviter de créer une classe Binding pour chaque route, ce qui est encore plus simple.
  329 +
  330 +Les deux méthodes fonctionnent parfaitement bien et nous voulons que vous utilisiez ce qui correspond le mieux à vos goûts.
  331 +
  332 +### SmartManagement
  333 +
  334 +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é.
  335 +C'est ce qu'on appelle le mode `full` de gestion des dépendances.
  336 +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.
  337 +
  338 +#### Comment changer
  339 +
  340 +Si vous souhaitez modifier cette configuration (dont vous n'avez généralement pas besoin), procédez comme suit:
  341 +
  342 +```dart
  343 +void main () {
  344 + runApp(
  345 + GetMaterialApp(
  346 + smartManagement: SmartManagement.onlyBuilders //Ici
  347 + home: Home(),
  348 + )
  349 + )
  350 +}
  351 +```
  352 +
  353 +#### SmartManagement.full
  354 +
  355 +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.
  356 +
  357 +#### SmartManagement.onlyBuilders
  358 +
  359 +Avec cette option, seuls les contrôleurs démarrés dans `init:` ou chargés dans un Binding avec `Get.lazyPut()` seront supprimés.
  360 +
  361 +Si vous utilisez `Get.put()` ou `Get.putAsync()` ou toute autre approche, SmartManagement n'aura pas les autorisations pour exclure cette dépendance.
  362 +
  363 +Avec le comportement par défaut, même les widgets instanciés avec "Get.put" seront supprimés, contrairement à SmartManagement.onlyBuilders.
  364 +
  365 +#### SmartManagement.keepFactory
  366 +
  367 +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.
  368 +
  369 +### Comment Bindings fonctionne sous le capot
  370 +
  371 +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.
  372 +Cela arrive si vite que l'analyseur ne pourra même pas l'enregistrer.
  373 +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.
  374 +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.
  375 +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.
  376 +Utilisez celui qui vous convient le mieux.
  377 +
  378 +## Notes
  379 +
  380 +- 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.
  381 +
  382 +- 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.
  383 + Cependant, si vous travaillez avec des services ou toute autre abstraction, je vous recommande d'utiliser Bindings pour une meilleure organisation.
  1 +- [Gestion de route](#gestion-de-route)
  2 + - [Utilisation](#utilisation)
  3 + - [Navigation sans nom](#navigation-sans-nom)
  4 + - [Navigation par nom](#navigation-par-nom)
  5 + - [Envoyer des données aux routes nommées](#envoyer-des-donnes-aux-routes-nommes)
  6 + - [Liens URL dynamiques](#liens-url-dynamiques)
  7 + - [Middleware](#middleware)
  8 + - [Navigation sans context](#navigation-sans-context)
  9 + - [SnackBars](#snackbars)
  10 + - [Dialogs](#dialogs)
  11 + - [BottomSheets](#bottomsheets)
  12 + - [Nested Navigation](#nested-navigation)
  13 +
  14 +# Gestion de route
  15 +
  16 +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.
  17 +
  18 +## Utilisation
  19 +
  20 +Ajoutez ceci à votre fichier pubspec.yaml:
  21 +
  22 +```yaml
  23 +dependencies:
  24 + get:
  25 +```
  26 +
  27 +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!
  28 +
  29 +```dart
  30 +GetMaterialApp( // Avant: MaterialApp(
  31 + home: MyHome(),
  32 +)
  33 +```
  34 +
  35 +## Navigation sans nom
  36 +
  37 +Pour accéder à un nouvel écran:
  38 +
  39 +```dart
  40 +Get.to(NextScreen());
  41 +```
  42 +
  43 +To close snackbars, dialogs, bottomsheets, or anything you would normally close with Navigator.pop(context);
  44 +Pour fermer les snackbars, dialogs, bottomsheets ou tout ce que vous fermez normalement avec Navigator.pop (context);
  45 +
  46 +```dart
  47 +Get.back();
  48 +```
  49 +
  50 +Pour aller à l'écran suivant et aucune option pour revenir à l'écran précédent (pour une utilisation dans SplashScreens, écrans de connexion, etc.)
  51 +
  52 +```dart
  53 +Get.off(NextScreen());
  54 +```
  55 +
  56 +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)
  57 +
  58 +```dart
  59 +Get.offAll(NextScreen());
  60 +```
  61 +
  62 +Pour naviguer vers l'écran suivant et recevoir ou mettre à jour des données dès que vous en revenez:
  63 +
  64 +```dart
  65 +var data = await Get.to(Payment());
  66 +```
  67 +
  68 +sur l'autre écran, envoyez les données pour l'écran précédent:
  69 +
  70 +```dart
  71 +Get.back(result: 'success');
  72 +```
  73 +
  74 +Et utilisez-les:
  75 +
  76 +ex:
  77 +
  78 +```dart
  79 +if(data == 'success') madeAnything();
  80 +```
  81 +
  82 +Vous ne voulez pas apprendre notre syntaxe?
  83 +Changez simplement le Navigateur (majuscule) en navigateur (minuscule), et vous aurez toutes les fonctions de la navigation standard, sans avoir à utiliser 'context'.
  84 +Exemple:
  85 +
  86 +```dart
  87 +
  88 +// Navigateur Flutter par défaut
  89 +Navigator.of(context).push(
  90 + context,
  91 + MaterialPageRoute(
  92 + builder: (BuildContext context) {
  93 + return HomePage();
  94 + },
  95 + ),
  96 +);
  97 +
  98 +// Utilisez la syntaxe Flutter sans avoir besoin de 'context'
  99 +navigator.push(
  100 + MaterialPageRoute(
  101 + builder: (_) {
  102 + return HomePage();
  103 + },
  104 + ),
  105 +);
  106 +
  107 +// Syntaxe Get (c'est beaucoup mieux, mais vous avez le droit d'être en désaccord)
  108 +Get.to(HomePage());
  109 +
  110 +
  111 +```
  112 +
  113 +## Navigation Par Nom
  114 +
  115 +- Si vous préférez naviguer par namedRoutes, Get prend également en charge cela.
  116 +
  117 +Pour aller à nextScreen
  118 +
  119 +```dart
  120 +Get.toNamed("/NextScreen");
  121 +```
  122 +
  123 +Pour naviguer et supprimer l'écran précédent du stack.
  124 +
  125 +```dart
  126 +Get.offNamed("/NextScreen");
  127 +```
  128 +
  129 +Pour naviguer et supprimer tous les écrans précédents du stack.
  130 +
  131 +```dart
  132 +Get.offAllNamed("/NextScreen");
  133 +```
  134 +
  135 +Pour définir des routes, utilisez GetMaterialApp:
  136 +
  137 +```dart
  138 +void main() {
  139 + runApp(
  140 + GetMaterialApp(
  141 + initialRoute: '/',
  142 + getPages: [
  143 + GetPage(name: '/', page: () => MyHomePage()),
  144 + GetPage(name: '/second', page: () => Second()),
  145 + GetPage(
  146 + name: '/third',
  147 + page: () => Third(),
  148 + transition: Transition.zoom
  149 + ),
  150 + ],
  151 + )
  152 + );
  153 +}
  154 +```
  155 +
  156 +Pour gérer la navigation vers des routes non définies (erreur 404), vous pouvez définir une page 'unknownRoute' dans GetMaterialApp.
  157 +
  158 +```dart
  159 +void main() {
  160 + runApp(
  161 + GetMaterialApp(
  162 + unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
  163 + initialRoute: '/',
  164 + getPages: [
  165 + GetPage(name: '/', page: () => MyHomePage()),
  166 + GetPage(name: '/second', page: () => Second()),
  167 + ],
  168 + )
  169 + );
  170 +}
  171 +```
  172 +
  173 +### Envoyer des données aux routes nommées
  174 +
  175 +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.
  176 +
  177 +```dart
  178 +Get.toNamed("/NextScreen", arguments: 'Get is the best');
  179 +```
  180 +
  181 +dans votre classe ou contrôleur:
  182 +
  183 +```dart
  184 +print(Get.arguments);
  185 +//montre: Get is the best
  186 +```
  187 +
  188 +### Liens URL dynamiques
  189 +
  190 +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.
  191 +
  192 +```dart
  193 +Get.offAllNamed("/NextScreen?device=phone&id=354&name=Enzo");
  194 +```
  195 +
  196 +sur votre classe controller/bloc/stateful/stateless:
  197 +
  198 +```dart
  199 +print(Get.parameters['id']);
  200 +// donne: 354
  201 +print(Get.parameters['name']);
  202 +// donne: Enzo
  203 +```
  204 +
  205 +Vous pouvez également recevoir facilement des paramètres nommés avec Get:
  206 +
  207 +```dart
  208 +void main() {
  209 + runApp(
  210 + GetMaterialApp(
  211 + initialRoute: '/',
  212 + getPages: [
  213 + GetPage(
  214 + name: '/',
  215 + page: () => MyHomePage(),
  216 + ),
  217 + GetPage(
  218 + name: '/profile/',
  219 + page: () => MyProfile(),
  220 + ),
  221 + //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.
  222 + GetPage(
  223 + name: '/profile/:user',
  224 + page: () => UserProfile(),
  225 + ),
  226 + GetPage(
  227 + name: '/third',
  228 + page: () => Third(),
  229 + transition: Transition.cupertino
  230 + ),
  231 + ],
  232 + )
  233 + );
  234 +}
  235 +```
  236 +
  237 +Envoyer des données sur le nom de la route
  238 +
  239 +```dart
  240 +Get.toNamed("/profile/34954");
  241 +```
  242 +
  243 +Sur le deuxième écran, recevez les données par paramètre
  244 +
  245 +```dart
  246 +print(Get.parameters['user']);
  247 +// donne: 34954
  248 +```
  249 +
  250 +ou envoyer plusieurs paramètres comme celui-ci
  251 +
  252 +```dart
  253 +Get.toNamed("/profile/34954?flag=true");
  254 +```
  255 +
  256 +Sur le deuxième écran, prenez les données par paramètres comme d'habitude
  257 +
  258 +```dart
  259 +print(Get.parameters['user']);
  260 +print(Get.parameters['flag']);
  261 +// donne: 34954 true
  262 +```
  263 +
  264 +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
  265 +
  266 +### Middleware
  267 +
  268 +Si vous souhaitez écouter les événements Get pour déclencher des actions, vous pouvez utiliser routingCallback pour le faire:
  269 +
  270 +```dart
  271 +GetMaterialApp(
  272 + routingCallback: (routing) {
  273 + if(routing.current == '/second'){
  274 + openAds();
  275 + }
  276 + }
  277 +)
  278 +```
  279 +
  280 +Si vous n'utilisez pas GetMaterialApp, vous pouvez utiliser l'API manuelle pour attacher l'observateur Middleware.
  281 +
  282 +```dart
  283 +void main() {
  284 + runApp(
  285 + MaterialApp(
  286 + onGenerateRoute: Router.generateRoute,
  287 + initialRoute: "/",
  288 + navigatorKey: Get.key,
  289 + navigatorObservers: [
  290 + GetObserver(MiddleWare.observer), // ICI !!!
  291 + ],
  292 + ),
  293 + );
  294 +}
  295 +```
  296 +
  297 +Créez une classe MiddleWare
  298 +
  299 +```dart
  300 +class MiddleWare {
  301 + static observer(Routing routing) {
  302 + /// Vous pouvez écouter en plus des routes, des snackbars, des dialogs et des bottomsheets sur chaque écran.
  303 + /// Si vous devez saisir l'un de ces 3 événements directement ici,
  304 + /// vous devez spécifier que l'événement est != Ce que vous essayez de faire.
  305 + if (routing.current == '/second' && !routing.isSnackbar) {
  306 + Get.snackbar("Hi", "You are on second route");
  307 + } else if (routing.current =='/third'){
  308 + print('dernière route');
  309 + }
  310 + }
  311 +}
  312 +```
  313 +
  314 +Maintenant, utilisez Get sur votre code:
  315 +
  316 +```dart
  317 +class First extends StatelessWidget {
  318 + @override
  319 + Widget build(BuildContext context) {
  320 + return Scaffold(
  321 + appBar: AppBar(
  322 + leading: IconButton(
  323 + icon: Icon(Icons.add),
  324 + onPressed: () {
  325 + Get.snackbar("hi", "i am a modern snackbar");
  326 + },
  327 + ),
  328 + title: Text('First Route'),
  329 + ),
  330 + body: Center(
  331 + child: ElevatedButton(
  332 + child: Text('Open route'),
  333 + onPressed: () {
  334 + Get.toNamed("/second");
  335 + },
  336 + ),
  337 + ),
  338 + );
  339 + }
  340 +}
  341 +
  342 +class Second extends StatelessWidget {
  343 + @override
  344 + Widget build(BuildContext context) {
  345 + return Scaffold(
  346 + appBar: AppBar(
  347 + leading: IconButton(
  348 + icon: Icon(Icons.add),
  349 + onPressed: () {
  350 + Get.snackbar("hi", "i am a modern snackbar");
  351 + },
  352 + ),
  353 + title: Text('second Route'),
  354 + ),
  355 + body: Center(
  356 + child: ElevatedButton(
  357 + child: Text('Open route'),
  358 + onPressed: () {
  359 + Get.toNamed("/third");
  360 + },
  361 + ),
  362 + ),
  363 + );
  364 + }
  365 +}
  366 +
  367 +class Third extends StatelessWidget {
  368 + @override
  369 + Widget build(BuildContext context) {
  370 + return Scaffold(
  371 + appBar: AppBar(
  372 + title: Text("Third Route"),
  373 + ),
  374 + body: Center(
  375 + child: ElevatedButton(
  376 + onPressed: () {
  377 + Get.back();
  378 + },
  379 + child: Text('Go back!'),
  380 + ),
  381 + ),
  382 + );
  383 + }
  384 +}
  385 +```
  386 +
  387 +## Navigation sans context
  388 +
  389 +### SnackBars
  390 +
  391 +Pour avoir un simple SnackBar avec Flutter, vous devez obtenir le 'context' de Scaffold, ou vous devez utiliser un GlobalKey attaché à votre Scaffold
  392 +
  393 +```dart
  394 +final snackBar = SnackBar(
  395 + content: Text('Hi!'),
  396 + action: SnackBarAction(
  397 + label: 'I am a old and ugly snackbar :(',
  398 + onPressed: (){}
  399 + ),
  400 +);
  401 +// Trouvez le scaffold dans l'arborescence des widgets et utilisez-le pour afficher un SnackBar.
  402 +Scaffold.of(context).showSnackBar(snackBar);
  403 +```
  404 +
  405 +Avec Get:
  406 +
  407 +```dart
  408 +Get.snackbar('Hi', 'i am a modern snackbar');
  409 +```
  410 +
  411 +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!
  412 +
  413 +```dart
  414 +Get.snackbar(
  415 + "Hey i'm a Get SnackBar!", // title
  416 + "C'est incroyable! J'utilise SnackBar sans context, sans code standard, sans Scaffold, c'est quelque chose de vraiment incroyable!", // message
  417 + icon: Icon(Icons.alarm),
  418 + shouldIconPulse: true,
  419 + onTap:(){},
  420 + barBlur: 20,
  421 + isDismissible: true,
  422 + duration: Duration(seconds: 3),
  423 +);
  424 +
  425 +
  426 + ////////// TOUTES LES FONCTIONNALITÉS //////////
  427 + // Color colorText,
  428 + // Duration duration,
  429 + // SnackPosition snackPosition,
  430 + // Widget titleText,
  431 + // Widget messageText,
  432 + // bool instantInit,
  433 + // Widget icon,
  434 + // bool shouldIconPulse,
  435 + // double maxWidth,
  436 + // EdgeInsets margin,
  437 + // EdgeInsets padding,
  438 + // double borderRadius,
  439 + // Color borderColor,
  440 + // double borderWidth,
  441 + // Color backgroundColor,
  442 + // Color leftBarIndicatorColor,
  443 + // List<BoxShadow> boxShadows,
  444 + // Gradient backgroundGradient,
  445 + // TextButton mainButton,
  446 + // OnTap onTap,
  447 + // bool isDismissible,
  448 + // bool showProgressIndicator,
  449 + // AnimationController progressIndicatorController,
  450 + // Color progressIndicatorBackgroundColor,
  451 + // Animation<Color> progressIndicatorValueColor,
  452 + // SnackStyle snackStyle,
  453 + // Curve forwardAnimationCurve,
  454 + // Curve reverseAnimationCurve,
  455 + // Duration animationDuration,
  456 + // double barBlur,
  457 + // double overlayBlur,
  458 + // Color overlayColor,
  459 + // Form userInputForm
  460 + ///////////////////////////////////
  461 +```
  462 +
  463 +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
  464 +`Get.rawSnackbar ();` qui fournit l'API brute sur laquelle Get.snackbar a été construit.
  465 +
  466 +### Dialogs
  467 +
  468 +Pour ouvrir un 'dialog':
  469 +
  470 +```dart
  471 +Get.dialog(VotreDialogWidget());
  472 +```
  473 +
  474 +Pour ouvrir le 'dialog' par défaut:
  475 +
  476 +```dart
  477 +Get.defaultDialog(
  478 + onConfirm: () => print("Ok"),
  479 + middleText: "Dialog made in 3 lines of code"
  480 +);
  481 +```
  482 +
  483 +Vous pouvez également utiliser Get.generalDialog au lieu de showGeneralDialog.
  484 +
  485 +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.
  486 +Pour les widgets qui n'utilisent pas Overlay, vous pouvez utiliser Get.context.
  487 +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.
  488 +
  489 +### BottomSheets
  490 +
  491 +Get.bottomSheet est comme showModalBottomSheet, mais n'a pas besoin de 'context'.
  492 +
  493 +```dart
  494 +Get.bottomSheet(
  495 + Container(
  496 + child: Wrap(
  497 + children: <Widget>[
  498 + ListTile(
  499 + leading: Icon(Icons.music_note),
  500 + title: Text('Music'),
  501 + onTap: () {}
  502 + ),
  503 + ListTile(
  504 + leading: Icon(Icons.videocam),
  505 + title: Text('Video'),
  506 + onTap: () {},
  507 + ),
  508 + ],
  509 + ),
  510 + )
  511 +);
  512 +```
  513 +
  514 +## Nested Navigation
  515 +
  516 +Getx a rendu la navigation imbriquée de Flutter encore plus facile.
  517 +Vous n'avez pas besoin de 'context' et vous trouverez votre stack de navigation par ID.
  518 +
  519 +- 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.
  520 +
  521 +Voyez comme c'est simple:
  522 +
  523 +```dart
  524 +Navigator(
  525 + key: Get.nestedKey(1), // créez une clé par index
  526 + initialRoute: '/',
  527 + onGenerateRoute: (settings) {
  528 + if (settings.name == '/') {
  529 + return GetPageRoute(
  530 + page: () => Scaffold(
  531 + appBar: AppBar(
  532 + title: Text("Main"),
  533 + ),
  534 + body: Center(
  535 + child: TextButton(
  536 + color: Colors.blue,
  537 + onPressed: () {
  538 + Get.toNamed('/second', id:1); // naviguer votre itinéraire imbriqué par index
  539 + },
  540 + child: Text("Go to second"),
  541 + ),
  542 + ),
  543 + ),
  544 + );
  545 + } else if (settings.name == '/second') {
  546 + return GetPageRoute(
  547 + page: () => Center(
  548 + child: Scaffold(
  549 + appBar: AppBar(
  550 + title: Text("Main"),
  551 + ),
  552 + body: Center(
  553 + child: Text("second")
  554 + ),
  555 + ),
  556 + ),
  557 + );
  558 + }
  559 + }
  560 +),
  561 +```
  1 +- [Gestion d'État](#gestion-d-etat)
  2 + - [Gestionnaire d'état réactif](#gestionnaire-d-etat-reactif)
  3 + - [Avantages](#avantages)
  4 + - [Performance maximale:](#performance-maximale)
  5 + - [Déclaration d'une variable réactive](#declaration-d-une-variable-reactive)
  6 + - [Avoir un état réactif, c'est facile.](#avoir-un-etat-reactif-c-est-facile)
  7 + - [Utilisation des valeurs dans la Vue](#utilisation-des-valeurs-dans-la-vue)
  8 + - [Conditions pour reconstruire](#conditions-pour-reconstruire)
  9 + - [Quand utiliser .obs](#quand-utiliser-obs)
  10 + - [Remarque sur List](#remarque-sur-list)
  11 + - [Pourquoi je dois utiliser .value](#pourquoi-je-dois-utiliser-value)
  12 + - [Obx()](#obx)
  13 + - [Workers](#workers)
  14 + - [Gestionnaire d'état simple](#gestionnaire-d-etat-simple)
  15 + - [Atouts](#atouts)
  16 + - [Utilisation](#utilisation)
  17 + - [Comment il gère les contrôleurs](#comment-il-gre-les-contrleurs)
  18 + - [Vous n'aurez plus besoin de StatefulWidgets](#vous-naurez-plus-besoin-de-statefulwidgets)
  19 + - [Pourquoi ça existe](#pourquoi-ca-existe)
  20 + - [Autres façons de l'utiliser](#autres-formes-d-utilisation)
  21 + - [IDs Uniques](#ids-uniques)
  22 + - [Mélanger les deux gestionnaires d'état](#mixing-the-two-state-managers)
  23 + - [GetBuilder vs GetX vs Obx vs MixinBuilder](#getbuilder-vs-getx-vs-obx-vs-mixinbuilder)
  24 +
  25 +# Gestion d Etat
  26 +
  27 +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.
  28 +
  29 +- _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.
  30 +- _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é.
  31 + 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.
  32 +- _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.
  33 +- _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.
  34 + 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.
  35 +- _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.
  36 + La plupart (sinon tous) les gestionnaires d'état actuels se reconstruiront à l'écran.
  37 +
  38 +## Gestionnaire d etat reactif
  39 +
  40 +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:
  41 +
  42 +- Vous n'aurez pas besoin de créer des StreamControllers.
  43 +- Vous n'aurez pas besoin de créer un StreamBuilder pour chaque variable
  44 +- Vous n'aurez pas besoin de créer une classe pour chaque état.
  45 +- Vous n'aurez pas besoin de créer un 'get' pour une valeur initiale.
  46 +
  47 +
  48 +La programmation réactive avec Get est aussi simple que d'utiliser setState.
  49 +
  50 +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.
  51 +
  52 +Voici votre variable:
  53 +
  54 +```dart
  55 +var name = 'Jonatas Borges';
  56 +```
  57 +
  58 +Pour la rendre observable, il vous suffit d'ajouter ".obs" à la fin:
  59 +
  60 +```dart
  61 +var name = 'Jonatas Borges'.obs;
  62 +```
  63 +
  64 +C'est *tout*. Si simple que ca.
  65 +
  66 +A partir de maintenant, nous pourrions désigner ces variables réactives - ". Obs" (ervables) comme _Rx_.
  67 +
  68 +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.
  69 +
  70 +C'est la **magie de GetX**, grâce aux performances de Dart.
  71 +
  72 +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 ".
  73 +
  74 +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?
  75 +
  76 +Non, vous n'avez pas besoin d'un `StreamBuilder`, mais vous avez raison pour les classes statiques.
  77 +
  78 +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.
  79 +Avec **GetX**, vous pouvez également oublier ce code passe-partout.
  80 +
  81 +`StreamBuilder( … )`? `initialValue: …`? `builder: …`? Non, il vous suffit de placer cette variable dans un widget `Obx()`.
  82 +
  83 +```dart
  84 +Obx (() => Text (controller.name));
  85 +```
  86 +
  87 +_Que devez-vous mémoriser?_ Seulement `Obx(() =>`.
  88 +
  89 +Vous passez simplement ce Widget via une fonction dans un `Obx()` (l' "Observateur" du _Rx_).
  90 +
  91 +`Obx` est assez intelligent et ne changera que si la valeur de` controller.name` change.
  92 +
  93 +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?**
  94 +
  95 +> Alors, que faire si j'ai 5 variables _Rx_ (observables) dans un `Obx`?
  96 +
  97 +Il sera simplement mis à jour lorsque **l'un d'entre eux** change.
  98 +
  99 +> 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?
  100 +
  101 +Non, juste le **Widget spécifique** qui utilise cette variable _Rx_.
  102 +
  103 +Ainsi, **GetX** ne met à jour l'écran que lorsque la variable _Rx_ change sa valeur.
  104 +
  105 +```
  106 +final isOpen = false.obs;
  107 +
  108 +// Rien de ne change... valeur identique.
  109 +void onButtonTap() => isOpen.value=false;
  110 +```
  111 +### Avantages
  112 +
  113 +**GetX()** vous aide lorsque vous avez besoin d'un contrôle **granulaire** sur ce qui est mis à jour.
  114 +
  115 +
  116 +Si vous n'avez pas besoin d'ID uniques, car toutes vos variables seront modifiées lorsque vous effectuez une action, utilisez `GetBuilder`,
  117 +parce que c'est un Simple State Updater (en blocs, comme `setState()`), fait en seulement quelques lignes de code.
  118 +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.
  119 +
  120 +Si vous avez besoin d'un State Manager **puissant** , vous ne pouvez pas vous tromper avec **GetX**.
  121 +
  122 +Cela ne fonctionne pas avec les variables, mais __flows__, tout ce qu'il contient sont des `Streams` en réalité.
  123 +Vous pouvez utiliser _rxDart_ en conjonction avec lui, car tout est `Streams`.
  124 +Vous pouvez écouter les changements de chaque "variable _Rx_",
  125 +parce que tout ce qui se trouve dedans est un `Streams`.
  126 +
  127 +
  128 +C'est littéralement une approche _BLoC_, plus facile que _MobX_, et sans générateurs de code ni décorations.
  129 +Vous pouvez transformer **n'importe quoi** en un _"Observable"_ avec juste un `.obs`.
  130 +
  131 +### Performance maximale:
  132 +
  133 +En plus d'avoir un algorithme intelligent pour des reconstructions minimales, **GetX** utilise des comparateurs
  134 +pour s'assurer que l'État a changé.
  135 +
  136 +Si vous rencontrez des erreurs dans votre application et envoyez un changement d'état en double,
  137 +**GetX** garantira qu'il ne plantera pas.
  138 +
  139 +Avec **GetX**, l'état ne change que si la `valeur` change.
  140 +C'est la principale différence entre **GetX** et l'utilisation de _`computed` de MobX_.
  141 +Lors de la jonction de deux __observables__, si l'une change; le listener de cet _observable_ changera également.
  142 +
  143 +Avec **GetX**, si vous joignez deux variables, `GetX()` (similaire à `Observer()`), ne se reconstruira que si cela implique un réel changement d'état.
  144 +
  145 +### Declaration d une variable reactive
  146 +
  147 +Vous avez 3 façons de transformer une variable en "observable".
  148 +
  149 +1 - La première est d'utiliser **`Rx{Type}`**.
  150 +
  151 +```dart
  152 +// la valeur initiale est recommandée, mais pas obligatoire
  153 +final name = RxString('');
  154 +final isLogged = RxBool(false);
  155 +final count = RxInt(0);
  156 +final balance = RxDouble(0.0);
  157 +final items = RxList<String>([]);
  158 +final myMap = RxMap<String, int>({});
  159 +```
  160 +
  161 +2 - La seconde consiste à utiliser **`Rx`** et à utiliser les types `Rx<Type>` Génériques Darts
  162 +
  163 +```dart
  164 +final name = Rx<String>('');
  165 +final isLogged = Rx<Bool>(false);
  166 +final count = Rx<Int>(0);
  167 +final balance = Rx<Double>(0.0);
  168 +final number = Rx<Num>(0);
  169 +final items = Rx<List<String>>([]);
  170 +final myMap = Rx<Map<String, int>>({});
  171 +
  172 +// Classes personnalisées - il peut s'agir de n'importe quelle classe, littéralement
  173 +final user = Rx<User>();
  174 +```
  175 +
  176 +3 - La troisième approche, plus pratique, plus facile et préférée, ajoutez simplement **`.obs`** comme propriété de votre` valeur`:
  177 +
  178 +```dart
  179 +final name = ''.obs;
  180 +final isLogged = false.obs;
  181 +final count = 0.obs;
  182 +final balance = 0.0.obs;
  183 +final number = 0.obs;
  184 +final items = <String>[].obs;
  185 +final myMap = <String, int>{}.obs;
  186 +
  187 +// Classes personnalisées - il peut s'agir de n'importe quelle classe, littéralement
  188 +final user = User().obs;
  189 +```
  190 +
  191 +##### Avoir un etat reactif, c est facile.
  192 +
  193 +Comme nous le savons, _Dart_ se dirige maintenant vers _null safety_.
  194 +Pour être prêt, à partir de maintenant, vous devez toujours commencer vos variables _Rx_ avec une **valeur initiale**.
  195 +
  196 +> Transformer une variable en _observable_ + _valeurInitiale_ avec **GetX** est l'approche la plus simple et la plus pratique.
  197 +
  198 +Vous allez littéralement ajouter un "".obs"" à la fin de votre variable, et **c'est tout**, vous l'avez rendue observable,
  199 +et sa `.value`, eh bien, sera la _valeurInitiale_.
  200 +
  201 +### Utilisation des valeurs dans la Vue
  202 +
  203 +```dart
  204 +// dans le controlleur
  205 +final count1 = 0.obs;
  206 +final count2 = 0.obs;
  207 +int get sum => count1.value + count2.value;
  208 +```
  209 +
  210 +```dart
  211 +// dans la vue
  212 +GetX<Controller>(
  213 + builder: (controller) {
  214 + print("count 1 reconstruction");
  215 + return Text('${controller.count1.value}');
  216 + },
  217 +),
  218 +GetX<Controller>(
  219 + builder: (controller) {
  220 + print("count 2 reconstruction");
  221 + return Text('${controller.count2.value}');
  222 + },
  223 +),
  224 +GetX<Controller>(
  225 + builder: (controller) {
  226 + print("count 3 reconstruction");
  227 + return Text('${controller.sum}');
  228 + },
  229 +),
  230 +```
  231 +
  232 +Si nous incrémentons `count1.value++`, cela affichera:
  233 +- `count 1 reconstruction`
  234 +- `count 3 reconstruction`
  235 +
  236 +parce que `count1` a une valeur de `1`, et `1 + 0 = 1`, changeant la valeur du getter `sum`.
  237 +
  238 +Si nous incrémentons `count2.value++`, cela affichera:
  239 +- `count 2 reconstruction`
  240 +- `count 3 reconstruction`
  241 +
  242 +parce que `count2.value` a changé et que le résultat de `sum` est maintenant `2`.
  243 +
  244 +- NOTE: Par défaut, le tout premier événement reconstruira le widget, même s'il s'agit de la même `valeur`.
  245 + Ce comportement existe en raison de variables booléennes.
  246 +
  247 +Imaginez que vous fassiez ceci:
  248 +
  249 +```dart
  250 +var isLogged = false.obs;
  251 +```
  252 +
  253 +Et puis, vous vérifiez si un utilisateur est "connecté" pour déclencher un événement dans `ever`.
  254 +
  255 +```dart
  256 +@override
  257 +onInit(){
  258 + ever(isLogged, fireRoute);
  259 + isLogged.value = await Preferences.hasToken();
  260 +}
  261 +
  262 +fireRoute(logged) {
  263 + if (logged) {
  264 + Get.off(Home());
  265 + } else {
  266 + Get.off(Login());
  267 + }
  268 +}
  269 +```
  270 +
  271 +si `hasToken` était `false`, il n'y aurait pas de changement à `isLogged`, donc` ever() `ne serait jamais appelé.
  272 +Pour éviter ce type de comportement, la première modification d'un _observable_ déclenchera toujours un événement,
  273 +même s'il contient la même `.value`.
  274 +
  275 +Vous pouvez supprimer ce comportement si vous le souhaitez, en utilisant:
  276 +`isLogged.firstRebuild = false;`
  277 +
  278 +### Conditions pour reconstruire
  279 +
  280 +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.
  281 +
  282 +```dart
  283 +// Premier paramètre: condition, doit retourner vrai ou faux.
  284 +// Deuxième paramètre: la nouvelle valeur à appliquer si la condition est vraie.
  285 +list.addIf(item < limit, item);
  286 +```
  287 +
  288 +Sans décorations, sans générateur de code, sans complications :smile:
  289 +
  290 +Connaissez-vous l'application 'counter' de Flutter? Votre classe Controller pourrait ressembler à ceci:
  291 +
  292 +```dart
  293 +class CountController extends GetxController {
  294 + final count = 0.obs;
  295 +}
  296 +```
  297 +
  298 +Avec un simple:
  299 +
  300 +```dart
  301 +controller.count.value++
  302 +```
  303 +
  304 +Vous pouvez mettre à jour la variable de compteur dans votre interface utilisateur, quel que soit l'endroit où elle est stockée.
  305 +
  306 +### Quand utiliser .obs
  307 +
  308 +Vous pouvez tout transformer sur obs. Voici deux façons de procéder:
  309 +
  310 +* Vous pouvez convertir vos valeurs de classe en obs
  311 +```dart
  312 +class RxUser {
  313 + final name = "Camila".obs;
  314 + final age = 18.obs;
  315 +}
  316 +```
  317 +
  318 +* ou vous pouvez convertir la classe entière en un observable:
  319 +```dart
  320 +class User {
  321 + User({String name, int age});
  322 + var name;
  323 + var age;
  324 +}
  325 +
  326 +// en instanciant:
  327 +final user = User(name: "Camila", age: 18).obs;
  328 +```
  329 +
  330 +### Remarque sur List
  331 +
  332 +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.
  333 +
  334 +Vous n'avez pas non plus besoin d'utiliser ".value" avec des listes, l'incroyable api de Dart nous a permis de supprimer cela.
  335 +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.
  336 +
  337 +```dart
  338 +// Dans le controlleur
  339 +final String title = 'User Info:'.obs;
  340 +final list = List<User>().obs;
  341 +
  342 +// Dans la vue
  343 +Text(controller.title.value), // La String doit avoir .value devant elle
  344 +ListView.builder (
  345 + itemCount: controller.list.length // pas besoin pour List
  346 +)
  347 +```
  348 +
  349 +Lorsque vous rendez vos propres classes observables, il existe une manière différente de les mettre à jour:
  350 +
  351 +```dart
  352 +// sur le fichier modèle
  353 +// nous allons rendre la classe entière observable au lieu de chaque attribut
  354 +class User() {
  355 + User({this.name = '', this.age = 0});
  356 + String name;
  357 + int age;
  358 +}
  359 +
  360 +
  361 +// Dans le controlleur
  362 +final user = User().obs;
  363 +// lorsque vous devez mettre à jour la variable utilisateur:
  364 +user.update( (user) { // ce paramètre est la classe même que vous souhaitez mettre à jour
  365 +user.name = 'Jonny';
  366 +user.age = 18;
  367 +});
  368 +// une autre manière de mettre à jour la variable user:
  369 +user(User(name: 'João', age: 35));
  370 +
  371 +// Dans la vue:
  372 +Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"))
  373 +// vous pouvez également accéder aux valeurs du modèle sans le .value:
  374 +user().name; //notez que c'est la variable utilisateur, pas la classe (la variable a un u minuscule)
  375 +```
  376 +
  377 +Vous n'êtes pas obligé de travailler avec des setters si vous ne le souhaitez pas. vous pouvez utiliser les API `assign` et `assignAll`.
  378 +L'API `assign` effacera votre liste et ajoutera un seul objet que vous souhaitez.
  379 +L'API `assignAll` effacera la liste existante et ajoutera tous les objets itérables que vous y injecterez.
  380 +
  381 +### Pourquoi je dois utiliser .value
  382 +
  383 +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.
  384 +
  385 +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.
  386 +
  387 +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.
  388 +
  389 +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.
  390 +
  391 +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.
  392 +
  393 +É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.
  394 +
  395 +### Obx()
  396 +
  397 +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.
  398 +É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 .
  399 +
  400 +### Workers
  401 +
  402 +Les 'workers' vous assisteront, déclenchant des callbacks spécifiques lorsqu'un événement se produit.
  403 +
  404 +```dart
  405 +/// Appelée à chaque fois que `count1` change.
  406 +ever(count1, (_) => print("$_ a été modifié"));
  407 +
  408 +/// Appelée uniquement la première fois que la variable est modifiée
  409 +once(count1, (_) => print("$_ a été changé une fois"));
  410 +
  411 +/// Anti DDos - Appelée chaque fois que l'utilisateur arrête de taper pendant 1 seconde, par exemple.
  412 +debounce(count1, (_) => print("debouce$_"), time: Duration(seconds: 1));
  413 +
  414 +/// Ignore toutes les modifications pendant 1 seconde.
  415 +interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
  416 +```
  417 +Tous les workers (sauf `debounce`) ont un paramètre nommé `condition`, qui peut etre un `bool` ou un callback qui retourne un `bool`.
  418 +Cette `condition` definit quand la fonction `callback` est executée.
  419 +
  420 +Tous les workers renvoyent un objet `Worker`, qui peut être utilisé pour annuler ( via `dispose()` ) le `worker`.
  421 +
  422 +- **`ever`**
  423 + est appelée chaque fois que la variable _Rx_ émet une nouvelle valeur.
  424 +
  425 +- **`everAll`**
  426 + 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.
  427 +
  428 +- **`once`**
  429 +'once' est appelée uniquement la première fois que la variable a été modifiée.
  430 +
  431 +- **`debounce`**
  432 +'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.
  433 +
  434 +- **`interval`**
  435 +'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.
  436 +
  437 +- 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).
  438 +
  439 +## Gestionnaire d etat simple
  440 +
  441 +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.
  442 +
  443 +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.
  444 +
  445 +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.
  446 +
  447 +### Atouts
  448 +
  449 +1. Met à jour uniquement les widgets requis.
  450 +
  451 +2. N'utilise pas changeNotifier, c'est le gestionnaire d'état qui utilise le moins de mémoire (proche de 0 Mo).
  452 +
  453 +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é.
  454 +
  455 +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.
  456 +
  457 +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.
  458 +
  459 +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.
  460 +
  461 +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).
  462 +
  463 +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.
  464 +
  465 +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.
  466 +
  467 +### Utilisation
  468 +
  469 +```dart
  470 +// Créez la classe controller qui 'extends' GetxController
  471 +class Controller extends GetxController {
  472 + int counter = 0;
  473 + void increment() {
  474 + counter++;
  475 + update(); // utilisez update() pour mettre à jour la variable de compteur sur l'interface utilisateur lorsque incrément() est appelé
  476 + }
  477 +}
  478 +// Sur votre classe Stateless / Stateful, utilisez GetBuilder pour mettre à jour le texte lorsque incrément() est appelé
  479 +GetBuilder<Controller>(
  480 + init: Controller(), // INITIER CA UNIQUEMENT LA PREMIÈRE FOIS
  481 + builder: (_) => Text(
  482 + '${_.counter}',
  483 + ),
  484 +)
  485 +//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.
  486 +```
  487 +
  488 +**Fait!**
  489 +
  490 +- Vous avez déjà appris à gérer les états avec Get.
  491 +
  492 +- 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.
  493 +
  494 +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):
  495 +
  496 +```dart
  497 +class OtherClass extends StatelessWidget {
  498 + @override
  499 + Widget build(BuildContext context) {
  500 + return Scaffold(
  501 + body: Center(
  502 + child: GetBuilder<Controller>(
  503 + builder: (s) => Text('${s.counter}'),
  504 + ),
  505 + ),
  506 + );
  507 + }
  508 +
  509 +```
  510 +
  511 +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>()`)
  512 +
  513 +```dart
  514 +class Controller extends GetxController {
  515 +
  516 + /// Vous n'en avez pas besoin. Je recommande de l'utiliser uniquement pour faciliter la syntaxe.
  517 + /// avec la méthode statique: Controller.to.counter();
  518 + /// sans méthode statique: Get.find<Controller>() .counter();
  519 + /// 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.
  520 + static Controller get to => Get.find(); // Ajouter cette ligne
  521 +
  522 + int counter = 0;
  523 + void increment() {
  524 + counter++;
  525 + update();
  526 + }
  527 +}
  528 +```
  529 +
  530 +Et puis vous pouvez accéder directement à votre contrôleur, de cette façon:
  531 +
  532 +```dart
  533 +FloatingActionButton(
  534 + onPressed:() {
  535 + Controller.to.increment(),
  536 + } // This is incredibly simple!
  537 + child: Text("${Controller.to.counter}"),
  538 +),
  539 +```
  540 +
  541 +Lorsque vous appuyez sur FloatingActionButton, tous les widgets qui écoutent la variable `counter` seront mis à jour automatiquement.
  542 +
  543 +### Comment il gère les contrôleurs
  544 +
  545 +Disons que nous avons ceci:
  546 +
  547 +`Class a => Class B (has controller X) => Class C (has controller X)`
  548 +
  549 +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.
  550 +
  551 +### Vous n'aurez plus besoin de StatefulWidgets
  552 +
  553 +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.
  554 +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!
  555 +À moins que vous n'ayez besoin d'utiliser un mixin, comme TickerProviderStateMixin, il sera totalement inutile d'utiliser un StatefulWidget avec Get.
  556 +
  557 +Vous pouvez appeler toutes les méthodes d'un StatefulWidget directement à partir d'un GetBuilder.
  558 +Si vous devez appeler la méthode initState() ou dispose() par exemple, vous pouvez les appeler directement:
  559 +
  560 +```dart
  561 +GetBuilder<Controller>(
  562 + initState: (_) => Controller.to.fetchApi(),
  563 + dispose: (_) => Controller.to.closeStreams(),
  564 + builder: (s) => Text('${s.username}'),
  565 +),
  566 +```
  567 +
  568 +Une bien meilleure approche que celle-ci consiste à utiliser les méthodes onInit() et onClose() directement à partir de votre contrôleur.
  569 +
  570 +```dart
  571 +@override
  572 +void onInit() {
  573 + fetchApi();
  574 + super.onInit();
  575 +}
  576 +```
  577 +
  578 +- 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.
  579 +
  580 +### Pourquoi ca existe
  581 +
  582 +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.
  583 +
  584 +Donc, pour simplifier cela:
  585 +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.
  586 +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.
  587 +
  588 +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:
  589 +
  590 +```dart
  591 +class Controller extends GetxController {
  592 + StreamController<User> user = StreamController<User>();
  593 + StreamController<String> name = StreamController<String>();
  594 +
  595 + /// pour fermer stream = méthode onClose(), pas dispose().
  596 + @override
  597 + void onClose() {
  598 + user.close();
  599 + name.close();
  600 + super.onClose();
  601 + }
  602 +}
  603 +```
  604 +
  605 +Cycle de vie du controlleur:
  606 +
  607 +- onInit() quand il est créé.
  608 +- onClose() quand il est fermé pour apporter des modifications en préparation de la méthode delete.
  609 +- 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.
  610 +
  611 +### Autres formes d utilisation
  612 +
  613 +Vous pouvez utiliser l'instance Controller directement sur la valeur GetBuilder:
  614 +
  615 +```dart
  616 +GetBuilder<Controller>(
  617 + init: Controller(),
  618 + builder: (value) => Text(
  619 + '${value.counter}', // ici
  620 + ),
  621 +),
  622 +```
  623 +
  624 +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:
  625 +
  626 +```dart
  627 +class Controller extends GetxController {
  628 + static Controller get to => Get.find();
  629 +[...]
  630 +}
  631 +// Dans la vue:
  632 +GetBuilder<Controller>(
  633 + init: Controller(), // utilisez-le seulement la première fois sur chaque contrôleur
  634 + builder: (_) => Text(
  635 + '${Controller.to.counter}', // ici
  636 + )
  637 +),
  638 +```
  639 +
  640 +ou encore
  641 +
  642 +```dart
  643 +class Controller extends GetxController {
  644 + // static Controller get to => Get.find(); // sans static get
  645 +[...]
  646 +}
  647 +// Dans la classe stateful/stateless
  648 +GetBuilder<Controller>(
  649 + init: Controller(), // utilisez-le seulement la première fois sur chaque contrôleur
  650 + builder: (_) => Text(
  651 + '${Get.find<Controller>().counter}', // ici
  652 + ),
  653 +),
  654 +```
  655 +
  656 +- 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:
  657 +
  658 +```dart
  659 +Controller controller = Controller();
  660 +[...]
  661 +GetBuilder<Controller>(
  662 + init: controller, // ici
  663 + builder: (_) => Text(
  664 + '${controller.counter}', // ici
  665 + ),
  666 +),
  667 +
  668 +```
  669 +
  670 +### IDs Uniques
  671 +
  672 +Si vous souhaitez affiner le contrôle de mise à jour d'un widget avec GetBuilder, vous pouvez leur attribuer des ID uniques:
  673 +
  674 +```dart
  675 +GetBuilder<Controller>(
  676 + id: 'text'
  677 + init: Controller(), // utilisez-le seulement la première fois sur chaque contrôleur
  678 + builder: (_) => Text(
  679 + '${Get.find<Controller>().counter}', // ici
  680 + ),
  681 +),
  682 +```
  683 +
  684 +Et mettez-le à jour de cette façon:
  685 +
  686 +```dart
  687 +update(['text']);
  688 +```
  689 +
  690 +Vous pouvez également imposer des conditions pour la mise à jour:
  691 +
  692 +```dart
  693 +update(['text'], counter < 10);
  694 +```
  695 +
  696 +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é ).
  697 +
  698 +## Mélanger les deux gestionnaires d'état
  699 +
  700 +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.
  701 +
  702 +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.
  703 +
  704 +## GetBuilder vs GetX vs Obx vs MixinBuilder
  705 +
  706 +En une décennie de travail avec la programmation, j'ai pu apprendre de précieuses leçons.
  707 +
  708 +Mon premier contact avec la programmation réactive a été tellement "wow, c'est incroyable" et en fait la programmation réactive est incroyable.
  709 +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.
  710 +
  711 +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.
  712 +
  713 +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.
  714 +
  715 +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).
  716 +
  717 +Cependant, GetBuilder est toujours un gestionnaire d'état mécanique, vous devez appeler update() comme vous auriez besoin d'appeler les notifyListeners() de Provider.
  718 +
  719 +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.
  720 +
  721 +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.
@@ -248,6 +248,21 @@ print(Get.parameters['user']); @@ -248,6 +248,21 @@ print(Get.parameters['user']);
248 // keluaran: 34954 248 // keluaran: 34954
249 ``` 249 ```
250 250
  251 +atau kirim beberapa parameter seperti ini
  252 +
  253 +```dart
  254 +Get.toNamed("/profile/34954?flag=true");
  255 +```
  256 +
  257 +Pada layar kedua, ambil data berdasarkan parameter seperti biasanya
  258 +
  259 +```dart
  260 +print(Get.parameters['user']);
  261 +print(Get.parameters['flag']);
  262 +// keluaran: 34954 true
  263 +```
  264 +
  265 +
251 Dan sekarang, yang anda perlu lakukan adalah menggunakan Get.toNamed() untuk bernavigasi ke named route anda, tanpa konteks (anda bisa memanggil route secara langsung dari kelas BLoC atau Controller), dan ketika aplikasi anda di-compile di web, route anda akan muncul di url <3 266 Dan sekarang, yang anda perlu lakukan adalah menggunakan Get.toNamed() untuk bernavigasi ke named route anda, tanpa konteks (anda bisa memanggil route secara langsung dari kelas BLoC atau Controller), dan ketika aplikasi anda di-compile di web, route anda akan muncul di url <3
252 267
253 ### Middleware 268 ### Middleware
@@ -315,7 +330,7 @@ class First extends StatelessWidget { @@ -315,7 +330,7 @@ class First extends StatelessWidget {
315 title: Text('Halaman Pertama'), 330 title: Text('Halaman Pertama'),
316 ), 331 ),
317 body: Center( 332 body: Center(
318 - child: RaisedButton( 333 + child: ElevatedButton(
319 child: Text('Pindah halaman'), 334 child: Text('Pindah halaman'),
320 onPressed: () { 335 onPressed: () {
321 Get.toNamed("/second"); 336 Get.toNamed("/second");
@@ -340,7 +355,7 @@ class Second extends StatelessWidget { @@ -340,7 +355,7 @@ class Second extends StatelessWidget {
340 title: Text('Halaman kedua'), 355 title: Text('Halaman kedua'),
341 ), 356 ),
342 body: Center( 357 body: Center(
343 - child: RaisedButton( 358 + child: ElevatedButton(
344 child: Text('Pindah halaman'), 359 child: Text('Pindah halaman'),
345 onPressed: () { 360 onPressed: () {
346 Get.toNamed("/third"); 361 Get.toNamed("/third");
@@ -359,7 +374,7 @@ class Third extends StatelessWidget { @@ -359,7 +374,7 @@ class Third extends StatelessWidget {
359 title: Text("Halaman ketiga"), 374 title: Text("Halaman ketiga"),
360 ), 375 ),
361 body: Center( 376 body: Center(
362 - child: RaisedButton( 377 + child: ElevatedButton(
363 onPressed: () { 378 onPressed: () {
364 Get.back(); 379 Get.back();
365 }, 380 },
@@ -430,7 +445,7 @@ Get.snackbar( @@ -430,7 +445,7 @@ Get.snackbar(
430 // Color leftBarIndicatorColor, 445 // Color leftBarIndicatorColor,
431 // List<BoxShadow> boxShadows, 446 // List<BoxShadow> boxShadows,
432 // Gradient backgroundGradient, 447 // Gradient backgroundGradient,
433 - // FlatButton mainButton, 448 + // TextButton mainButton,
434 // OnTap onTap, 449 // OnTap onTap,
435 // bool isDismissible, 450 // bool isDismissible,
436 // bool showProgressIndicator, 451 // bool showProgressIndicator,
@@ -520,7 +535,7 @@ Navigator( @@ -520,7 +535,7 @@ Navigator(
520 title: Text("Main"), 535 title: Text("Main"),
521 ), 536 ),
522 body: Center( 537 body: Center(
523 - child: FlatButton( 538 + child: TextButton(
524 color: Colors.blue, 539 color: Colors.blue,
525 onPressed: () { 540 onPressed: () {
526 Get.toNamed('/second', id:1); // pindah ke halaman bersarang anda menggunakan index 541 Get.toNamed('/second', id:1); // pindah ke halaman bersarang anda menggunakan index
@@ -246,6 +246,23 @@ print(Get.parameters['user']); @@ -246,6 +246,23 @@ print(Get.parameters['user']);
246 // 출력: 34954 246 // 출력: 34954
247 ``` 247 ```
248 248
  249 +
  250 +또는 이와 같은 여러 매개 변수를 보냅니다.
  251 +
  252 +```dart
  253 +Get.toNamed("/profile/34954?flag=true");
  254 +```
  255 +
  256 +두 번째 화면에서 일반적으로 매개 변수별로 데이터를 가져옵니다.
  257 +
  258 +```dart
  259 +print(Get.parameters['user']);
  260 +print(Get.parameters['flag']);
  261 +// 출력: 34954 true
  262 +```
  263 +
  264 +
  265 +
249 이제 Get.toNamed()를 사용하여 어떤 context도 없이 명명된 라우트를 탐색하고 (BLoC 또는 Controller 클래스로 부터 직접 라우트를 호출할 수 있음) 앱이 웹으로 컴파일되면 경로는 url에 표시됩니다. <3 266 이제 Get.toNamed()를 사용하여 어떤 context도 없이 명명된 라우트를 탐색하고 (BLoC 또는 Controller 클래스로 부터 직접 라우트를 호출할 수 있음) 앱이 웹으로 컴파일되면 경로는 url에 표시됩니다. <3
250 267
251 ### 미들웨어 268 ### 미들웨어
@@ -313,7 +330,7 @@ class First extends StatelessWidget { @@ -313,7 +330,7 @@ class First extends StatelessWidget {
313 title: Text('First Route'), 330 title: Text('First Route'),
314 ), 331 ),
315 body: Center( 332 body: Center(
316 - child: RaisedButton( 333 + child: ElevatedButton(
317 child: Text('Open route'), 334 child: Text('Open route'),
318 onPressed: () { 335 onPressed: () {
319 Get.toNamed("/second"); 336 Get.toNamed("/second");
@@ -338,7 +355,7 @@ class Second extends StatelessWidget { @@ -338,7 +355,7 @@ class Second extends StatelessWidget {
338 title: Text('second Route'), 355 title: Text('second Route'),
339 ), 356 ),
340 body: Center( 357 body: Center(
341 - child: RaisedButton( 358 + child: ElevatedButton(
342 child: Text('Open route'), 359 child: Text('Open route'),
343 onPressed: () { 360 onPressed: () {
344 Get.toNamed("/third"); 361 Get.toNamed("/third");
@@ -357,7 +374,7 @@ class Third extends StatelessWidget { @@ -357,7 +374,7 @@ class Third extends StatelessWidget {
357 title: Text("Third Route"), 374 title: Text("Third Route"),
358 ), 375 ),
359 body: Center( 376 body: Center(
360 - child: RaisedButton( 377 + child: ElevatedButton(
361 onPressed: () { 378 onPressed: () {
362 Get.back(); 379 Get.back();
363 }, 380 },
@@ -428,7 +445,7 @@ Get.snackbar( @@ -428,7 +445,7 @@ Get.snackbar(
428 // Color leftBarIndicatorColor, 445 // Color leftBarIndicatorColor,
429 // List<BoxShadow> boxShadows, 446 // List<BoxShadow> boxShadows,
430 // Gradient backgroundGradient, 447 // Gradient backgroundGradient,
431 - // FlatButton mainButton, 448 + // TextButton mainButton,
432 // OnTap onTap, 449 // OnTap onTap,
433 // bool isDismissible, 450 // bool isDismissible,
434 // bool showProgressIndicator, 451 // bool showProgressIndicator,
@@ -518,7 +535,7 @@ Navigator( @@ -518,7 +535,7 @@ Navigator(
518 title: Text("Main"), 535 title: Text("Main"),
519 ), 536 ),
520 body: Center( 537 body: Center(
521 - child: FlatButton( 538 + child: TextButton(
522 color: Colors.blue, 539 color: Colors.blue,
523 onPressed: () { 540 onPressed: () {
524 Get.toNamed('/second', id:1); // index로 중첩된 경로를 탐색 541 Get.toNamed('/second', id:1); // index로 중첩된 경로를 탐색
@@ -140,7 +140,7 @@ Get.snackbar( @@ -140,7 +140,7 @@ Get.snackbar(
140 // Color leftBarIndicatorColor, 140 // Color leftBarIndicatorColor,
141 // List<BoxShadow> boxShadows, 141 // List<BoxShadow> boxShadows,
142 // Gradient backgroundGradient, 142 // Gradient backgroundGradient,
143 - // FlatButton mainButton, 143 + // TextButton mainButton,
144 // OnTap onTap, 144 // OnTap onTap,
145 // bool isDismissible, 145 // bool isDismissible,
146 // bool showProgressIndicator, 146 // bool showProgressIndicator,
@@ -322,9 +322,26 @@ Get.toNamed("/segunda/34954"); @@ -322,9 +322,26 @@ Get.toNamed("/segunda/34954");
322 Na segunda tela receba os dados usando `Get.parameters[]` 322 Na segunda tela receba os dados usando `Get.parameters[]`
323 323
324 ```dart 324 ```dart
325 -print(Get.parameters['user']); // valor: 34954 325 +print(Get.parameters['user']);
  326 +// valor: 34954
326 ``` 327 ```
327 328
  329 +
  330 +ou envie vários parâmetros como este
  331 +
  332 +```dart
  333 +Get.toNamed("/profile/34954?flag=true");
  334 +```
  335 +
  336 +Na segunda tela, pegue os dados por parâmetros normalmente
  337 +```dart
  338 +print(Get.parameters['user']);
  339 +print(Get.parameters['flag']);
  340 +// valor: 34954 true
  341 +```
  342 +
  343 +
  344 +
328 E agora, tudo que você precisa fazer é usar `Get.toNamed)` para navegar por suas rotas nomeadas, sem nenhum `context` (você pode chamar suas rotas diretamente do seu BLoc ou do Controller), e quando seu aplicativo é compilado para a web, suas rotas vão aparecer na url ❤ 345 E agora, tudo que você precisa fazer é usar `Get.toNamed)` para navegar por suas rotas nomeadas, sem nenhum `context` (você pode chamar suas rotas diretamente do seu BLoc ou do Controller), e quando seu aplicativo é compilado para a web, suas rotas vão aparecer na url ❤
329 346
330 #### Middleware 347 #### Middleware
@@ -393,7 +410,7 @@ class Primeira extends StatelessWidget { @@ -393,7 +410,7 @@ class Primeira extends StatelessWidget {
393 title: Text('Primeira rota'), 410 title: Text('Primeira rota'),
394 ), 411 ),
395 body: Center( 412 body: Center(
396 - child: RaisedButton( 413 + child: ElevatedButton(
397 child: Text('Abrir rota'), 414 child: Text('Abrir rota'),
398 onPressed: () { 415 onPressed: () {
399 Get.toNamed("/segunda"); 416 Get.toNamed("/segunda");
@@ -418,7 +435,7 @@ class Segunda extends StatelessWidget { @@ -418,7 +435,7 @@ class Segunda extends StatelessWidget {
418 title: Text('Segunda rota'), 435 title: Text('Segunda rota'),
419 ), 436 ),
420 body: Center( 437 body: Center(
421 - child: RaisedButton( 438 + child: ElevatedButton(
422 child: Text('Abrir rota'), 439 child: Text('Abrir rota'),
423 onPressed: () { 440 onPressed: () {
424 Get.toNamed("/terceira"); 441 Get.toNamed("/terceira");
@@ -437,7 +454,7 @@ class Terceira extends StatelessWidget { @@ -437,7 +454,7 @@ class Terceira extends StatelessWidget {
437 title: Text("Terceira Rota"), 454 title: Text("Terceira Rota"),
438 ), 455 ),
439 body: Center( 456 body: Center(
440 - child: RaisedButton( 457 + child: ElevatedButton(
441 onPressed: () { 458 onPressed: () {
442 Get.back(); 459 Get.back();
443 }, 460 },
@@ -512,7 +529,7 @@ Navigator( @@ -512,7 +529,7 @@ Navigator(
512 title: Text("Principal"), 529 title: Text("Principal"),
513 ), 530 ),
514 body: Center( 531 body: Center(
515 - child: FlatButton( 532 + child: TextButton(
516 color: Colors.blue, 533 color: Colors.blue,
517 child: Text("Ir para a segunda"), 534 child: Text("Ir para a segunda"),
518 onPressed: () { 535 onPressed: () {
@@ -246,6 +246,22 @@ print(Get.parameters['user']); @@ -246,6 +246,22 @@ print(Get.parameters['user']);
246 // out: 34954 246 // out: 34954
247 ``` 247 ```
248 248
  249 +или отправьте несколько таких параметров
  250 +
  251 +```dart
  252 +Get.toNamed("/profile/34954?flag=true");
  253 +```
  254 +
  255 +На втором экране взять данные по параметрам как обычно.
  256 +
  257 +```dart
  258 +print(Get.parameters['user']);
  259 +print(Get.parameters['flag']);
  260 +// out: 34954 true
  261 +```
  262 +
  263 +
  264 +
249 И теперь все, что вам нужно сделать, это использовать Get.toNamed() для навигации по именованным маршрутам без какого-либо контекста (вы можете вызывать свои маршруты непосредственно из класса BLoC или контроллера), а когда ваше приложение будет скомпилировано в Интернете, ваше маршруты появятся в url <3 265 И теперь все, что вам нужно сделать, это использовать Get.toNamed() для навигации по именованным маршрутам без какого-либо контекста (вы можете вызывать свои маршруты непосредственно из класса BLoC или контроллера), а когда ваше приложение будет скомпилировано в Интернете, ваше маршруты появятся в url <3
250 266
251 ### Middleware 267 ### Middleware
@@ -313,7 +329,7 @@ class First extends StatelessWidget { @@ -313,7 +329,7 @@ class First extends StatelessWidget {
313 title: Text('First Route'), 329 title: Text('First Route'),
314 ), 330 ),
315 body: Center( 331 body: Center(
316 - child: RaisedButton( 332 + child: ElevatedButton(
317 child: Text('Open route'), 333 child: Text('Open route'),
318 onPressed: () { 334 onPressed: () {
319 Get.toNamed("/second"); 335 Get.toNamed("/second");
@@ -338,7 +354,7 @@ class Second extends StatelessWidget { @@ -338,7 +354,7 @@ class Second extends StatelessWidget {
338 title: Text('second Route'), 354 title: Text('second Route'),
339 ), 355 ),
340 body: Center( 356 body: Center(
341 - child: RaisedButton( 357 + child: ElevatedButton(
342 child: Text('Open route'), 358 child: Text('Open route'),
343 onPressed: () { 359 onPressed: () {
344 Get.toNamed("/third"); 360 Get.toNamed("/third");
@@ -357,7 +373,7 @@ class Third extends StatelessWidget { @@ -357,7 +373,7 @@ class Third extends StatelessWidget {
357 title: Text("Third Route"), 373 title: Text("Third Route"),
358 ), 374 ),
359 body: Center( 375 body: Center(
360 - child: RaisedButton( 376 + child: ElevatedButton(
361 onPressed: () { 377 onPressed: () {
362 Get.back(); 378 Get.back();
363 }, 379 },
@@ -428,7 +444,7 @@ Get.snackbar( @@ -428,7 +444,7 @@ Get.snackbar(
428 // Color leftBarIndicatorColor, 444 // Color leftBarIndicatorColor,
429 // List<BoxShadow> boxShadows, 445 // List<BoxShadow> boxShadows,
430 // Gradient backgroundGradient, 446 // Gradient backgroundGradient,
431 - // FlatButton mainButton, 447 + // TextButton mainButton,
432 // OnTap onTap, 448 // OnTap onTap,
433 // bool isDismissible, 449 // bool isDismissible,
434 // bool showProgressIndicator, 450 // bool showProgressIndicator,
@@ -518,7 +534,7 @@ Navigator( @@ -518,7 +534,7 @@ Navigator(
518 title: Text("Main"), 534 title: Text("Main"),
519 ), 535 ),
520 body: Center( 536 body: Center(
521 - child: FlatButton( 537 + child: TextButton(
522 color: Colors.blue, 538 color: Colors.blue,
523 onPressed: () { 539 onPressed: () {
524 Get.toNamed('/second', id:1); // navigate by your nested route by index 540 Get.toNamed('/second', id:1); // navigate by your nested route by index
@@ -243,6 +243,21 @@ print(Get.parameters['user']); @@ -243,6 +243,21 @@ print(Get.parameters['user']);
243 // out: 34954 243 // out: 34954
244 ``` 244 ```
245 245
  246 +或像这样发送多个参数
  247 +
  248 +```dart
  249 +Get.toNamed("/profile/34954?flag=true");
  250 +```
  251 +
  252 +在第二个屏幕上,通常按参数获取数据
  253 +
  254 +```dart
  255 +print(Get.parameters['user']);
  256 +print(Get.parameters['flag']);
  257 +// out: 34954 true
  258 +```
  259 +
  260 +
246 现在,你需要做的就是使用Get.toNamed()来导航你的别名路由,不需要任何context(你可以直接从你的BLoC或Controller类中调用你的路由),当你的应用程序被编译到web时,你的路由将出现在URL中。 261 现在,你需要做的就是使用Get.toNamed()来导航你的别名路由,不需要任何context(你可以直接从你的BLoC或Controller类中调用你的路由),当你的应用程序被编译到web时,你的路由将出现在URL中。
247 262
248 ### 中间件 263 ### 中间件
@@ -308,7 +323,7 @@ class First extends StatelessWidget { @@ -308,7 +323,7 @@ class First extends StatelessWidget {
308 title: Text('First Route'), 323 title: Text('First Route'),
309 ), 324 ),
310 body: Center( 325 body: Center(
311 - child: RaisedButton( 326 + child: ElevatedButton(
312 child: Text('Open route'), 327 child: Text('Open route'),
313 onPressed: () { 328 onPressed: () {
314 Get.toNamed("/second"); 329 Get.toNamed("/second");
@@ -333,7 +348,7 @@ class Second extends StatelessWidget { @@ -333,7 +348,7 @@ class Second extends StatelessWidget {
333 title: Text('second Route'), 348 title: Text('second Route'),
334 ), 349 ),
335 body: Center( 350 body: Center(
336 - child: RaisedButton( 351 + child: ElevatedButton(
337 child: Text('Open route'), 352 child: Text('Open route'),
338 onPressed: () { 353 onPressed: () {
339 Get.toNamed("/third"); 354 Get.toNamed("/third");
@@ -352,7 +367,7 @@ class Third extends StatelessWidget { @@ -352,7 +367,7 @@ class Third extends StatelessWidget {
352 title: Text("Third Route"), 367 title: Text("Third Route"),
353 ), 368 ),
354 body: Center( 369 body: Center(
355 - child: RaisedButton( 370 + child: ElevatedButton(
356 onPressed: () { 371 onPressed: () {
357 Get.back(); 372 Get.back();
358 }, 373 },
@@ -422,7 +437,7 @@ Get.snackbar( @@ -422,7 +437,7 @@ Get.snackbar(
422 // Color leftBarIndicatorColor, 437 // Color leftBarIndicatorColor,
423 // List<BoxShadow> boxShadows, 438 // List<BoxShadow> boxShadows,
424 // Gradient backgroundGradient, 439 // Gradient backgroundGradient,
425 - // FlatButton mainButton, 440 + // TextButton mainButton,
426 // OnTap onTap, 441 // OnTap onTap,
427 // bool isDismissible, 442 // bool isDismissible,
428 // bool showProgressIndicator, 443 // bool showProgressIndicator,
@@ -512,7 +527,7 @@ Navigator( @@ -512,7 +527,7 @@ Navigator(
512 title: Text("Main"), 527 title: Text("Main"),
513 ), 528 ),
514 body: Center( 529 body: Center(
515 - child: FlatButton( 530 + child: TextButton(
516 color: Colors.blue, 531 color: Colors.blue,
517 onPressed: () { 532 onPressed: () {
518 Get.toNamed('/second', id:1); // navigate by your nested route by index 533 Get.toNamed('/second', id:1); // navigate by your nested route by index
@@ -343,25 +343,24 @@ ListView.builder ( @@ -343,25 +343,24 @@ ListView.builder (
343 ```dart 343 ```dart
344 // model 344 // model
345 // 我们将使整个类成为可观察的,而不是每个属性。 345 // 我们将使整个类成为可观察的,而不是每个属性。
346 -class User() { 346 +class User{
347 User({this.name = '', this.age = 0}); 347 User({this.name = '', this.age = 0});
348 String name; 348 String name;
349 int age; 349 int age;
350 } 350 }
351 351
352 -  
353 // controller 352 // controller
354 final user = User().obs; 353 final user = User().obs;
355 //当你需要更新user变量时。 354 //当你需要更新user变量时。
356 user.update( (user) { // 这个参数是你要更新的类本身。 355 user.update( (user) { // 这个参数是你要更新的类本身。
357 -user.name = 'Jonny';  
358 -user.age = 18; 356 + user.name = 'Jonny';
  357 + user.age = 18;
359 }); 358 });
360 // 更新user变量的另一种方式。 359 // 更新user变量的另一种方式。
361 user(User(name: 'João', age: 35)); 360 user(User(name: 'João', age: 35));
362 361
363 // view 362 // view
364 -Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}")) 363 +Obx(()=> Text("Name ${user.value.name}: Age: ${user.value.age}"));
365 // 你也可以不使用.value来访问模型值。 364 // 你也可以不使用.value来访问模型值。
366 user().name; // 注意是user变量,而不是类变量(首字母是小写的)。 365 user().name; // 注意是user变量,而不是类变量(首字母是小写的)。
367 ``` 366 ```
@@ -666,7 +665,7 @@ GetBuilder<Controller>( @@ -666,7 +665,7 @@ GetBuilder<Controller>(
666 665
667 ```dart 666 ```dart
668 GetBuilder<Controller>( 667 GetBuilder<Controller>(
669 - id: 'text' 、、这里 668 + id: 'text', //这里
670 init: Controller(), // 每个控制器只用一次 669 init: Controller(), // 每个控制器只用一次
671 builder: (_) => Text( 670 builder: (_) => Text(
672 '${Get.find<Controller>().counter}', //here 671 '${Get.find<Controller>().counter}', //here
@@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
33 /ios/ 33 /ios/
34 /android/ 34 /android/
35 /web/ 35 /web/
  36 +/macos/
36 37
37 # Web related 38 # Web related
38 lib/generated_plugin_registrant.dart 39 lib/generated_plugin_registrant.dart
@@ -53,7 +53,7 @@ class Home extends StatelessWidget { @@ -53,7 +53,7 @@ class Home extends StatelessWidget {
53 builder: (_) => Text( 53 builder: (_) => Text(
54 'clicks: ${controller.count}', 54 'clicks: ${controller.count}',
55 )), 55 )),
56 - RaisedButton( 56 + ElevatedButton(
57 child: Text('Next Route'), 57 child: Text('Next Route'),
58 onPressed: () { 58 onPressed: () {
59 Get.to(Second()); 59 Get.to(Second());
@@ -120,7 +120,7 @@ class Home extends StatelessWidget { @@ -120,7 +120,7 @@ class Home extends StatelessWidget {
120 builder: (_) => Text( 120 builder: (_) => Text(
121 'clicks: ${controller.count}', 121 'clicks: ${controller.count}',
122 )), 122 )),
123 - RaisedButton( 123 + ElevatedButton(
124 child: Text('Next Route'), 124 child: Text('Next Route'),
125 onPressed: () { 125 onPressed: () {
126 Get.to(Second()); 126 Get.to(Second());
@@ -161,7 +161,7 @@ class Home extends StatelessWidget { @@ -161,7 +161,7 @@ class Home extends StatelessWidget {
161 Obx(() => Text( 161 Obx(() => Text(
162 'clicks: ${controller.count}', 162 'clicks: ${controller.count}',
163 )), 163 )),
164 - RaisedButton( 164 + ElevatedButton(
165 child: Text('Next Route'), 165 child: Text('Next Route'),
166 onPressed: () { 166 onPressed: () {
167 Get.to(Second()); 167 Get.to(Second());
@@ -362,13 +362,13 @@ class First extends StatelessWidget { @@ -362,13 +362,13 @@ class First extends StatelessWidget {
362 builder: (_) => Text( 362 builder: (_) => Text(
363 'clicks: ${_.count}', 363 'clicks: ${_.count}',
364 )), 364 )),
365 - RaisedButton( 365 + ElevatedButton(
366 child: Text('Next Route'), 366 child: Text('Next Route'),
367 onPressed: () { 367 onPressed: () {
368 Get.toNamed('/second'); 368 Get.toNamed('/second');
369 }, 369 },
370 ), 370 ),
371 - RaisedButton( 371 + ElevatedButton(
372 child: Text('Change locale to English'), 372 child: Text('Change locale to English'),
373 onPressed: () { 373 onPressed: () {
374 Get.updateLocale(Locale('en', 'UK')); 374 Get.updateLocale(Locale('en', 'UK'));
@@ -421,13 +421,13 @@ class Second extends GetView<ControllerX> { @@ -421,13 +421,13 @@ class Second extends GetView<ControllerX> {
421 GetX<ControllerX>( 421 GetX<ControllerX>(
422 builder: (_) => Text('Age: ${_.user.value.age}'), 422 builder: (_) => Text('Age: ${_.user.value.age}'),
423 ), 423 ),
424 - RaisedButton( 424 + ElevatedButton(
425 child: Text("Go to last page"), 425 child: Text("Go to last page"),
426 onPressed: () { 426 onPressed: () {
427 Get.toNamed('/third', arguments: 'arguments of second'); 427 Get.toNamed('/third', arguments: 'arguments of second');
428 }, 428 },
429 ), 429 ),
430 - RaisedButton( 430 + ElevatedButton(
431 child: Text("Back page and open snackbar"), 431 child: Text("Back page and open snackbar"),
432 onPressed: () { 432 onPressed: () {
433 Get.back(); 433 Get.back();
@@ -437,25 +437,25 @@ class Second extends GetView<ControllerX> { @@ -437,25 +437,25 @@ class Second extends GetView<ControllerX> {
437 ); 437 );
438 }, 438 },
439 ), 439 ),
440 - RaisedButton( 440 + ElevatedButton(
441 child: Text("Increment"), 441 child: Text("Increment"),
442 onPressed: () { 442 onPressed: () {
443 Get.find<ControllerX>().increment(); 443 Get.find<ControllerX>().increment();
444 }, 444 },
445 ), 445 ),
446 - RaisedButton( 446 + ElevatedButton(
447 child: Text("Increment"), 447 child: Text("Increment"),
448 onPressed: () { 448 onPressed: () {
449 Get.find<ControllerX>().increment2(); 449 Get.find<ControllerX>().increment2();
450 }, 450 },
451 ), 451 ),
452 - RaisedButton( 452 + ElevatedButton(
453 child: Text("Update name"), 453 child: Text("Update name"),
454 onPressed: () { 454 onPressed: () {
455 Get.find<ControllerX>().updateUser(); 455 Get.find<ControllerX>().updateUser();
456 }, 456 },
457 ), 457 ),
458 - RaisedButton( 458 + ElevatedButton(
459 child: Text("Dispose worker"), 459 child: Text("Dispose worker"),
460 onPressed: () { 460 onPressed: () {
461 Get.find<ControllerX>().disposeWorker(); 461 Get.find<ControllerX>().disposeWorker();
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 3
4 -import 'en_US.dart';  
5 -import 'pt_BR.dart'; 4 +import 'en_us.dart';
  5 +import 'pt_br.dart';
6 6
7 class TranslationService extends Translations { 7 class TranslationService extends Translations {
8 - static final locale = Get.deviceLocale; 8 + static Locale get locale => Get.deviceLocale!;
9 static final fallbackLocale = Locale('en', 'US'); 9 static final fallbackLocale = Locale('en', 'US');
10 @override 10 @override
11 Map<String, Map<String, String>> get keys => { 11 Map<String, Map<String, String>> get keys => {
@@ -9,10 +9,11 @@ void main() { @@ -9,10 +9,11 @@ void main() {
9 } 9 }
10 10
11 class MyApp extends StatelessWidget { 11 class MyApp extends StatelessWidget {
12 - const MyApp({Key key}) : super(key: key); 12 + const MyApp({Key? key}) : super(key: key);
13 13
14 @override 14 @override
15 Widget build(BuildContext context) { 15 Widget build(BuildContext context) {
  16 + Get.theme!.accentColor;
16 return GetMaterialApp( 17 return GetMaterialApp(
17 debugShowCheckedModeBanner: false, 18 debugShowCheckedModeBanner: false,
18 enableLog: true, 19 enableLog: true,
@@ -9,7 +9,8 @@ abstract class IHomeProvider { @@ -9,7 +9,8 @@ abstract class IHomeProvider {
9 class HomeProvider extends GetConnect implements IHomeProvider { 9 class HomeProvider extends GetConnect implements IHomeProvider {
10 @override 10 @override
11 void onInit() { 11 void onInit() {
12 - httpClient.defaultDecoder = CasesModel.fromJson; 12 + httpClient.defaultDecoder =
  13 + (val) => CasesModel.fromJson(val as Map<String, dynamic>);
13 httpClient.baseUrl = 'https://api.covid19api.com'; 14 httpClient.baseUrl = 'https://api.covid19api.com';
14 } 15 }
15 16
@@ -3,16 +3,16 @@ import '../domain/entity/cases_model.dart'; @@ -3,16 +3,16 @@ import '../domain/entity/cases_model.dart';
3 import 'home_api_provider.dart'; 3 import 'home_api_provider.dart';
4 4
5 class HomeRepository implements IHomeRepository { 5 class HomeRepository implements IHomeRepository {
6 - HomeRepository({this.provider}); 6 + HomeRepository({required this.provider});
7 final IHomeProvider provider; 7 final IHomeProvider provider;
8 8
9 @override 9 @override
10 Future<CasesModel> getCases() async { 10 Future<CasesModel> getCases() async {
11 final cases = await provider.getCases("/summary"); 11 final cases = await provider.getCases("/summary");
12 if (cases.status.hasError) { 12 if (cases.status.hasError) {
13 - return Future.error(cases.statusText); 13 + return Future.error(cases.statusText!);
14 } else { 14 } else {
15 - return cases.body; 15 + return cases.body!;
16 } 16 }
17 } 17 }
18 } 18 }
1 // To parse this JSON data, do 1 // To parse this JSON data, do
2 // 2 //
3 -// final CasesModel = CasesModelFromJson(jsonString); 3 +// final welcome = welcomeFromJson(jsonString);
4 4
5 import 'dart:convert'; 5 import 'dart:convert';
6 6
7 class CasesModel { 7 class CasesModel {
8 - final Global global;  
9 - final List<Country> countries;  
10 - final String date;  
11 -  
12 CasesModel({ 8 CasesModel({
13 - this.global,  
14 - this.countries,  
15 - this.date, 9 + required this.id,
  10 + required this.message,
  11 + required this.global,
  12 + required this.countries,
  13 + required this.date,
16 }); 14 });
17 15
18 - static CasesModel fromRawJson(String str) => 16 + final String id;
  17 + final String message;
  18 + final Global global;
  19 + final List<Country> countries;
  20 + final DateTime date;
  21 +
  22 + factory CasesModel.fromRawJson(String str) =>
19 CasesModel.fromJson(json.decode(str) as Map<String, dynamic>); 23 CasesModel.fromJson(json.decode(str) as Map<String, dynamic>);
20 24
21 String toRawJson() => json.encode(toJson()); 25 String toRawJson() => json.encode(toJson());
22 26
23 - static CasesModel fromJson(dynamic json) => CasesModel(  
24 - global: json["Global"] == null  
25 - ? null  
26 - : Global.fromJson(json["Global"] as Map<String, dynamic>),  
27 - countries: json["Countries"] == null  
28 - ? null  
29 - : List<Country>.from(  
30 - (json["Countries"] as List<dynamic>)  
31 - .map((x) => Country.fromJson(x as Map<String, dynamic>)),  
32 - ),  
33 - date: json["Date"] == null ? null : json["Date"] as String, 27 + factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel(
  28 + id: json["ID"] as String,
  29 + message: json["Message"] as String,
  30 + global: Global.fromJson(json["Global"] as Map<String, dynamic>),
  31 + countries: List<Country>.from((json["Countries"] as Iterable).map(
  32 + (x) => Country.fromJson(x as Map<String, dynamic>),
  33 + )),
  34 + date: DateTime.parse(json["Date"] as String),
34 ); 35 );
35 36
36 Map<String, dynamic> toJson() => { 37 Map<String, dynamic> toJson() => {
37 - "Global": global == null ? null : global.toJson(),  
38 - "Countries": countries == null  
39 - ? null  
40 - : List<dynamic>.from(countries.map((x) => x.toJson())),  
41 - "Date": date == null ? null : date, 38 + "ID": id,
  39 + "Message": message,
  40 + "Global": global.toJson(),
  41 + "Countries": List<dynamic>.from(countries.map((x) => x.toJson())),
  42 + "Date": date.toIso8601String(),
42 }; 43 };
43 } 44 }
44 45
45 class Country { 46 class Country {
  47 + Country({
  48 + required this.id,
  49 + required this.country,
  50 + required this.countryCode,
  51 + required this.slug,
  52 + required this.newConfirmed,
  53 + required this.totalConfirmed,
  54 + required this.newDeaths,
  55 + required this.totalDeaths,
  56 + required this.newRecovered,
  57 + required this.totalRecovered,
  58 + required this.date,
  59 + required this.premium,
  60 + });
  61 +
  62 + final String id;
46 final String country; 63 final String country;
47 final String countryCode; 64 final String countryCode;
48 final String slug; 65 final String slug;
@@ -52,20 +69,8 @@ class Country { @@ -52,20 +69,8 @@ class Country {
52 final int totalDeaths; 69 final int totalDeaths;
53 final int newRecovered; 70 final int newRecovered;
54 final int totalRecovered; 71 final int totalRecovered;
55 - final String date;  
56 -  
57 - Country({  
58 - this.country,  
59 - this.countryCode,  
60 - this.slug,  
61 - this.newConfirmed,  
62 - this.totalConfirmed,  
63 - this.newDeaths,  
64 - this.totalDeaths,  
65 - this.newRecovered,  
66 - this.totalRecovered,  
67 - this.date,  
68 - }); 72 + final DateTime date;
  73 + final Premium premium;
69 74
70 factory Country.fromRawJson(String str) => 75 factory Country.fromRawJson(String str) =>
71 Country.fromJson(json.decode(str) as Map<String, dynamic>); 76 Country.fromJson(json.decode(str) as Map<String, dynamic>);
@@ -73,56 +78,67 @@ class Country { @@ -73,56 +78,67 @@ class Country {
73 String toRawJson() => json.encode(toJson()); 78 String toRawJson() => json.encode(toJson());
74 79
75 factory Country.fromJson(Map<String, dynamic> json) => Country( 80 factory Country.fromJson(Map<String, dynamic> json) => Country(
76 - country: json["Country"] == null ? null : json["Country"] as String,  
77 - countryCode:  
78 - json["CountryCode"] == null ? null : json["CountryCode"] as String,  
79 - slug: json["Slug"] == null ? null : json["Slug"] as String,  
80 - newConfirmed:  
81 - json["NewConfirmed"] == null ? null : json["NewConfirmed"] as int,  
82 - totalConfirmed: json["TotalConfirmed"] == null  
83 - ? null  
84 - : json["TotalConfirmed"] as int,  
85 - newDeaths: json["NewDeaths"] == null ? null : json["NewDeaths"] as int,  
86 - totalDeaths:  
87 - json["TotalDeaths"] == null ? null : json["TotalDeaths"] as int,  
88 - newRecovered:  
89 - json["NewRecovered"] == null ? null : json["NewRecovered"] as int,  
90 - totalRecovered: json["TotalRecovered"] == null  
91 - ? null  
92 - : json["TotalRecovered"] as int,  
93 - date: json["Date"] == null ? null : json["Date"] as String, 81 + id: json["ID"] as String,
  82 + country: json["Country"] as String,
  83 + countryCode: json["CountryCode"] as String,
  84 + slug: json["Slug"] as String,
  85 + newConfirmed: json["NewConfirmed"] as int,
  86 + totalConfirmed: json["TotalConfirmed"] as int,
  87 + newDeaths: json["NewDeaths"] as int,
  88 + totalDeaths: json["TotalDeaths"] as int,
  89 + newRecovered: json["NewRecovered"] as int,
  90 + totalRecovered: json["TotalRecovered"] as int,
  91 + date: DateTime.parse(json["Date"] as String),
  92 + premium: Premium.fromJson(json["Premium"] as Map<String, dynamic>),
94 ); 93 );
95 94
96 Map<String, dynamic> toJson() => { 95 Map<String, dynamic> toJson() => {
97 - "Country": country == null ? null : country,  
98 - "CountryCode": countryCode == null ? null : countryCode,  
99 - "Slug": slug == null ? null : slug,  
100 - "NewConfirmed": newConfirmed == null ? null : newConfirmed,  
101 - "TotalConfirmed": totalConfirmed == null ? null : totalConfirmed,  
102 - "NewDeaths": newDeaths == null ? null : newDeaths,  
103 - "TotalDeaths": totalDeaths == null ? null : totalDeaths,  
104 - "NewRecovered": newRecovered == null ? null : newRecovered,  
105 - "TotalRecovered": totalRecovered == null ? null : totalRecovered,  
106 - "Date": date == null ? null : date, 96 + "ID": id,
  97 + "Country": country,
  98 + "CountryCode": countryCode,
  99 + "Slug": slug,
  100 + "NewConfirmed": newConfirmed,
  101 + "TotalConfirmed": totalConfirmed,
  102 + "NewDeaths": newDeaths,
  103 + "TotalDeaths": totalDeaths,
  104 + "NewRecovered": newRecovered,
  105 + "TotalRecovered": totalRecovered,
  106 + "Date": date.toIso8601String(),
  107 + "Premium": premium.toJson(),
107 }; 108 };
108 } 109 }
109 110
  111 +class Premium {
  112 + Premium();
  113 +
  114 + factory Premium.fromRawJson(String str) =>
  115 + Premium.fromJson(json.decode(str) as Map<String, dynamic>);
  116 +
  117 + String toRawJson() => json.encode(toJson());
  118 +
  119 + factory Premium.fromJson(Map<String, dynamic> json) => Premium();
  120 +
  121 + Map<String, dynamic> toJson() => {};
  122 +}
  123 +
110 class Global { 124 class Global {
  125 + Global({
  126 + required this.newConfirmed,
  127 + required this.totalConfirmed,
  128 + required this.newDeaths,
  129 + required this.totalDeaths,
  130 + required this.newRecovered,
  131 + required this.totalRecovered,
  132 + required this.date,
  133 + });
  134 +
111 final int newConfirmed; 135 final int newConfirmed;
112 final int totalConfirmed; 136 final int totalConfirmed;
113 final int newDeaths; 137 final int newDeaths;
114 final int totalDeaths; 138 final int totalDeaths;
115 final int newRecovered; 139 final int newRecovered;
116 final int totalRecovered; 140 final int totalRecovered;
117 -  
118 - Global({  
119 - this.newConfirmed,  
120 - this.totalConfirmed,  
121 - this.newDeaths,  
122 - this.totalDeaths,  
123 - this.newRecovered,  
124 - this.totalRecovered,  
125 - }); 141 + final DateTime date;
126 142
127 factory Global.fromRawJson(String str) => 143 factory Global.fromRawJson(String str) =>
128 Global.fromJson(json.decode(str) as Map<String, dynamic>); 144 Global.fromJson(json.decode(str) as Map<String, dynamic>);
@@ -130,27 +146,22 @@ class Global { @@ -130,27 +146,22 @@ class Global {
130 String toRawJson() => json.encode(toJson()); 146 String toRawJson() => json.encode(toJson());
131 147
132 factory Global.fromJson(Map<String, dynamic> json) => Global( 148 factory Global.fromJson(Map<String, dynamic> json) => Global(
133 - newConfirmed:  
134 - json["NewConfirmed"] == null ? null : json["NewConfirmed"] as int,  
135 - totalConfirmed: json["TotalConfirmed"] == null  
136 - ? null  
137 - : json["TotalConfirmed"] as int,  
138 - newDeaths: json["NewDeaths"] == null ? null : json["NewDeaths"] as int,  
139 - totalDeaths:  
140 - json["TotalDeaths"] == null ? null : json["TotalDeaths"] as int,  
141 - newRecovered:  
142 - json["NewRecovered"] == null ? null : json["NewRecovered"] as int,  
143 - totalRecovered: json["TotalRecovered"] == null  
144 - ? null  
145 - : json["TotalRecovered"] as int, 149 + newConfirmed: json["NewConfirmed"] as int,
  150 + totalConfirmed: json["TotalConfirmed"] as int,
  151 + newDeaths: json["NewDeaths"] as int,
  152 + totalDeaths: json["TotalDeaths"] as int,
  153 + newRecovered: json["NewRecovered"] as int,
  154 + totalRecovered: json["TotalRecovered"] as int,
  155 + date: DateTime.parse(json["Date"] as String),
146 ); 156 );
147 157
148 Map<String, dynamic> toJson() => { 158 Map<String, dynamic> toJson() => {
149 - "NewConfirmed": newConfirmed == null ? null : newConfirmed,  
150 - "TotalConfirmed": totalConfirmed == null ? null : totalConfirmed,  
151 - "NewDeaths": newDeaths == null ? null : newDeaths,  
152 - "TotalDeaths": totalDeaths == null ? null : totalDeaths,  
153 - "NewRecovered": newRecovered == null ? null : newRecovered,  
154 - "TotalRecovered": totalRecovered == null ? null : totalRecovered, 159 + "NewConfirmed": newConfirmed,
  160 + "TotalConfirmed": totalConfirmed,
  161 + "NewDeaths": newDeaths,
  162 + "TotalDeaths": totalDeaths,
  163 + "NewRecovered": newRecovered,
  164 + "TotalRecovered": totalRecovered,
  165 + "Date": date.toIso8601String(),
155 }; 166 };
156 } 167 }
@@ -4,22 +4,16 @@ import '../../domain/adapters/repository_adapter.dart'; @@ -4,22 +4,16 @@ import '../../domain/adapters/repository_adapter.dart';
4 import '../../domain/entity/cases_model.dart'; 4 import '../../domain/entity/cases_model.dart';
5 5
6 class HomeController extends SuperController<CasesModel> { 6 class HomeController extends SuperController<CasesModel> {
7 - HomeController({this.homeRepository}); 7 + HomeController({required this.homeRepository});
8 8
9 - /// inject repo abstraction dependency  
10 final IHomeRepository homeRepository; 9 final IHomeRepository homeRepository;
11 10
12 - /// When the controller is initialized, make the http request  
13 @override 11 @override
14 void onInit() { 12 void onInit() {
15 super.onInit(); 13 super.onInit();
16 - // show loading on start, data on success  
17 - // and error message on error with 0 boilerplate  
18 - homeRepository.getCases().then((data) {  
19 - change(data, status: RxStatus.success());  
20 - }, onError: (err) {  
21 - change(null, status: RxStatus.error(err.toString()));  
22 - }); 14 +
  15 + //Loading, Success, Error handle with 1 line of code
  16 + append(() => homeRepository.getCases);
23 } 17 }
24 18
25 @override 19 @override
@@ -29,9 +29,9 @@ class CountryView extends GetView<HomeController> { @@ -29,9 +29,9 @@ class CountryView extends GetView<HomeController> {
29 ), 29 ),
30 body: Center( 30 body: Center(
31 child: ListView.builder( 31 child: ListView.builder(
32 - itemCount: controller.state.countries.length, 32 + itemCount: controller.state!.countries.length,
33 itemBuilder: (context, index) { 33 itemBuilder: (context, index) {
34 - final country = controller.state.countries[index]; 34 + final country = controller.state!.countries[index];
35 return ListTile( 35 return ListTile(
36 onTap: () { 36 onTap: () {
37 Get.toNamed('/home/country/details', 37 Get.toNamed('/home/country/details',
@@ -42,7 +42,7 @@ class HomeView extends GetView<HomeController> { @@ -42,7 +42,7 @@ class HomeView extends GetView<HomeController> {
42 ), 42 ),
43 ), 43 ),
44 Text( 44 Text(
45 - '${state.global.totalConfirmed}', 45 + '${state!.global.totalConfirmed}',
46 style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 46 style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
47 ), 47 ),
48 SizedBox( 48 SizedBox(
@@ -61,18 +61,24 @@ class HomeView extends GetView<HomeController> { @@ -61,18 +61,24 @@ class HomeView extends GetView<HomeController> {
61 SizedBox( 61 SizedBox(
62 height: 10, 62 height: 10,
63 ), 63 ),
64 - OutlineButton(  
65 - borderSide: BorderSide( 64 + OutlinedButton(
  65 + style: OutlinedButton.styleFrom(
  66 + textStyle: TextStyle(color: Colors.black),
  67 + side: BorderSide(
66 color: Colors.deepPurple, 68 color: Colors.deepPurple,
67 width: 3, 69 width: 3,
68 ), 70 ),
69 shape: StadiumBorder(), 71 shape: StadiumBorder(),
  72 + ),
70 onPressed: () { 73 onPressed: () {
71 Get.toNamed('/home/country'); 74 Get.toNamed('/home/country');
72 }, 75 },
73 child: Text( 76 child: Text(
74 'fetch_country'.tr, 77 'fetch_country'.tr,
75 - style: TextStyle(fontWeight: FontWeight.bold), 78 + style: TextStyle(
  79 + fontWeight: FontWeight.bold,
  80 + color: Colors.black,
  81 + ),
76 ), 82 ),
77 ) 83 )
78 ], 84 ],
@@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev @@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
18 version: 1.0.0+1 18 version: 1.0.0+1
19 19
20 environment: 20 environment:
21 - sdk: ">=2.7.0 <3.0.0" 21 + sdk: ">=2.12.0 <3.0.0"
22 22
23 dependencies: 23 dependencies:
24 flutter: 24 flutter:
@@ -28,7 +28,7 @@ dependencies: @@ -28,7 +28,7 @@ dependencies:
28 # Use with the CupertinoIcons class for iOS style icons. 28 # Use with the CupertinoIcons class for iOS style icons.
29 get: 29 get:
30 path: ../ 30 path: ../
31 - get_test: ^3.13.3 31 + #get_test: ^3.13.3
32 32
33 dependency_overrides: 33 dependency_overrides:
34 get: 34 get:
@@ -6,8 +6,8 @@ import 'package:get/get.dart'; @@ -6,8 +6,8 @@ import 'package:get/get.dart';
6 import 'package:get_demo/pages/home/domain/adapters/repository_adapter.dart'; 6 import 'package:get_demo/pages/home/domain/adapters/repository_adapter.dart';
7 import 'package:get_demo/pages/home/domain/entity/cases_model.dart'; 7 import 'package:get_demo/pages/home/domain/entity/cases_model.dart';
8 import 'package:get_demo/pages/home/presentation/controllers/home_controller.dart'; 8 import 'package:get_demo/pages/home/presentation/controllers/home_controller.dart';
9 -import 'package:get_demo/routes/app_pages.dart';  
10 -import 'package:get_test/get_test.dart'; 9 +// import 'package:get_demo/routes/app_pages.dart';
  10 +// import 'package:get_test/get_test.dart';
11 import 'package:matcher/matcher.dart' as m; 11 import 'package:matcher/matcher.dart' as m;
12 12
13 class MockRepository implements IHomeRepository { 13 class MockRepository implements IHomeRepository {
@@ -17,7 +17,18 @@ class MockRepository implements IHomeRepository { @@ -17,7 +17,18 @@ class MockRepository implements IHomeRepository {
17 17
18 if (Random().nextBool()) { 18 if (Random().nextBool()) {
19 return CasesModel( 19 return CasesModel(
20 - global: Global(totalDeaths: 100, totalConfirmed: 200), 20 + global: Global(
  21 + totalDeaths: 100,
  22 + totalConfirmed: 200,
  23 + date: DateTime.now(),
  24 + newConfirmed: 0,
  25 + newDeaths: 0,
  26 + newRecovered: 0,
  27 + totalRecovered: 0),
  28 + countries: [],
  29 + date: DateTime.now(),
  30 + id: '',
  31 + message: '',
21 ); 32 );
22 } 33 }
23 34
@@ -26,6 +37,7 @@ class MockRepository implements IHomeRepository { @@ -26,6 +37,7 @@ class MockRepository implements IHomeRepository {
26 } 37 }
27 38
28 void main() { 39 void main() {
  40 + WidgetsFlutterBinding.ensureInitialized();
29 setUpAll(() => HttpOverrides.global = null); 41 setUpAll(() => HttpOverrides.global = null);
30 final binding = BindingsBuilder(() { 42 final binding = BindingsBuilder(() {
31 Get.lazyPut<IHomeRepository>(() => MockRepository()); 43 Get.lazyPut<IHomeRepository>(() => MockRepository());
@@ -69,13 +81,25 @@ void main() { @@ -69,13 +81,25 @@ void main() {
69 } 81 }
70 82
71 if (controller.status.isSuccess) { 83 if (controller.status.isSuccess) {
72 - expect(controller.state.global.totalDeaths, 100);  
73 - expect(controller.state.global.totalConfirmed, 200); 84 + expect(controller.state!.global.totalDeaths, 100);
  85 + expect(controller.state!.global.totalConfirmed, 200);
74 } 86 }
75 }); 87 });
76 88
  89 + test('ever', () async {
  90 + final count = ''.obs;
  91 + var result = '';
  92 + ever<String>(count, (value) {
  93 + result = value;
  94 + });
  95 + count.value = '1';
  96 + expect('1', result);
  97 + });
  98 +
77 /// Tests with GetTests 99 /// Tests with GetTests
78 - getTest( 100 + /// TEMPORARILY REMOVED from the null-safetym branch as
  101 + /// get_test is not yet null safety.
  102 + /* getTest(
79 "test description", 103 "test description",
80 getPages: AppPages.routes, 104 getPages: AppPages.routes,
81 initialRoute: AppPages.INITIAL, 105 initialRoute: AppPages.INITIAL,
@@ -104,33 +128,6 @@ void main() { @@ -104,33 +128,6 @@ void main() {
104 ), 128 ),
105 test: (e) { 129 test: (e) {
106 expect(find.text("ban:0"), findsOneWidget); 130 expect(find.text("ban:0"), findsOneWidget);
107 - expect(e.count.value, 0);  
108 - },  
109 - );  
110 -  
111 - testGetBuilder(  
112 - 'GetBuilder test',  
113 - widget: GetBuilder<Controller>(  
114 - init: Controller(),  
115 - builder: (controller) {  
116 - return Text("ban:${controller.count}");  
117 - },  
118 - ),  
119 - test: (e) {  
120 - expect(find.text("ban:0"), findsOneWidget);  
121 - expect(e.count.value, 0);  
122 - },  
123 - );  
124 -  
125 - testObx(  
126 - 'Obx test',  
127 - widget: (controller) => Obx(  
128 - () => Text("ban:${controller.count}"),  
129 - ),  
130 - controller: Controller(),  
131 - test: (e) {  
132 - expect(find.text("ban:0"), findsOneWidget);  
133 - expect(e.count.value, 0);  
134 }, 131 },
135 ); 132 );
136 133
@@ -151,7 +148,7 @@ void main() { @@ -151,7 +148,7 @@ void main() {
151 onClose: (c) { 148 onClose: (c) {
152 print('onClose'); 149 print('onClose');
153 }, 150 },
154 - ); 151 + );*/
155 } 152 }
156 153
157 class Controller extends GetxController { 154 class Controller extends GetxController {
@@ -13,74 +13,74 @@ export 'http/src/response/response.dart'; @@ -13,74 +13,74 @@ export 'http/src/response/response.dart';
13 export 'sockets/sockets.dart'; 13 export 'sockets/sockets.dart';
14 14
15 abstract class GetConnectInterface with GetLifeCycleBase { 15 abstract class GetConnectInterface with GetLifeCycleBase {
16 - List<GetSocket> sockets; 16 + List<GetSocket>? sockets;
17 GetHttpClient get httpClient; 17 GetHttpClient get httpClient;
18 18
19 Future<Response<T>> get<T>( 19 Future<Response<T>> get<T>(
20 String url, { 20 String url, {
21 - Map<String, String> headers,  
22 - String contentType,  
23 - Map<String, dynamic> query,  
24 - Decoder<T> decoder, 21 + Map<String, String>? headers,
  22 + String? contentType,
  23 + Map<String, dynamic>? query,
  24 + Decoder<T>? decoder,
25 }); 25 });
26 26
27 Future<Response<T>> request<T>( 27 Future<Response<T>> request<T>(
28 String url, 28 String url,
29 String method, { 29 String method, {
30 dynamic body, 30 dynamic body,
31 - String contentType,  
32 - Map<String, String> headers,  
33 - Map<String, dynamic> query,  
34 - Decoder<T> decoder, 31 + String? contentType,
  32 + Map<String, String>? headers,
  33 + Map<String, dynamic>? query,
  34 + Decoder<T>? decoder,
35 }); 35 });
36 Future<Response<T>> post<T>( 36 Future<Response<T>> post<T>(
37 String url, 37 String url,
38 dynamic body, { 38 dynamic body, {
39 - String contentType,  
40 - Map<String, String> headers,  
41 - Map<String, dynamic> query,  
42 - Decoder<T> decoder, 39 + String? contentType,
  40 + Map<String, String>? headers,
  41 + Map<String, dynamic>? query,
  42 + Decoder<T>? decoder,
43 }); 43 });
44 44
45 Future<Response<T>> put<T>( 45 Future<Response<T>> put<T>(
46 String url, 46 String url,
47 dynamic body, { 47 dynamic body, {
48 - String contentType,  
49 - Map<String, String> headers,  
50 - Map<String, dynamic> query,  
51 - Decoder<T> decoder, 48 + String? contentType,
  49 + Map<String, String>? headers,
  50 + Map<String, dynamic>? query,
  51 + Decoder<T>? decoder,
52 }); 52 });
53 53
54 Future<Response<T>> delete<T>( 54 Future<Response<T>> delete<T>(
55 String url, { 55 String url, {
56 - Map<String, String> headers,  
57 - String contentType,  
58 - Map<String, dynamic> query,  
59 - Decoder<T> decoder, 56 + Map<String, String>? headers,
  57 + String? contentType,
  58 + Map<String, dynamic>? query,
  59 + Decoder<T>? decoder,
60 }); 60 });
61 61
62 Future<Response<T>> patch<T>( 62 Future<Response<T>> patch<T>(
63 String url, 63 String url,
64 dynamic body, { 64 dynamic body, {
65 - String contentType,  
66 - Map<String, String> headers,  
67 - Map<String, dynamic> query,  
68 - Decoder<T> decoder,  
69 - Progress uploadProgress, 65 + String? contentType,
  66 + Map<String, String>? headers,
  67 + Map<String, dynamic>? query,
  68 + Decoder<T>? decoder,
  69 + Progress? uploadProgress,
70 }); 70 });
71 71
72 Future<GraphQLResponse<T>> query<T>( 72 Future<GraphQLResponse<T>> query<T>(
73 String query, { 73 String query, {
74 - String url,  
75 - Map<String, dynamic> variables,  
76 - Map<String, String> headers, 74 + String? url,
  75 + Map<String, dynamic>? variables,
  76 + Map<String, String>? headers,
77 }); 77 });
78 78
79 Future<GraphQLResponse<T>> mutation<T>( 79 Future<GraphQLResponse<T>> mutation<T>(
80 String mutation, { 80 String mutation, {
81 - String url,  
82 - Map<String, dynamic> variables,  
83 - Map<String, String> headers, 81 + String? url,
  82 + Map<String, dynamic>? variables,
  83 + Map<String, String>? headers,
84 }); 84 });
85 85
86 GetSocket socket( 86 GetSocket socket(
@@ -103,16 +103,16 @@ class GetConnect extends GetConnectInterface { @@ -103,16 +103,16 @@ class GetConnect extends GetConnectInterface {
103 103
104 bool allowAutoSignedCert; 104 bool allowAutoSignedCert;
105 String userAgent; 105 String userAgent;
106 - String baseUrl; 106 + String? baseUrl;
107 String defaultContentType = 'application/json; charset=utf-8'; 107 String defaultContentType = 'application/json; charset=utf-8';
108 bool followRedirects; 108 bool followRedirects;
109 int maxRedirects; 109 int maxRedirects;
110 int maxAuthRetries; 110 int maxAuthRetries;
111 - Decoder defaultDecoder; 111 + Decoder? defaultDecoder;
112 Duration timeout; 112 Duration timeout;
113 - List<TrustedCertificate> trustedCertificates;  
114 - GetHttpClient _httpClient;  
115 - List<GetSocket> _sockets; 113 + List<TrustedCertificate>? trustedCertificates;
  114 + GetHttpClient? _httpClient;
  115 + List<GetSocket>? _sockets;
116 116
117 @override 117 @override
118 List<GetSocket> get sockets => _sockets ??= <GetSocket>[]; 118 List<GetSocket> get sockets => _sockets ??= <GetSocket>[];
@@ -132,10 +132,10 @@ class GetConnect extends GetConnectInterface { @@ -132,10 +132,10 @@ class GetConnect extends GetConnectInterface {
132 @override 132 @override
133 Future<Response<T>> get<T>( 133 Future<Response<T>> get<T>(
134 String url, { 134 String url, {
135 - Map<String, String> headers,  
136 - String contentType,  
137 - Map<String, dynamic> query,  
138 - Decoder<T> decoder, 135 + Map<String, String>? headers,
  136 + String? contentType,
  137 + Map<String, dynamic>? query,
  138 + Decoder<T>? decoder,
139 }) { 139 }) {
140 _checkIfDisposed(); 140 _checkIfDisposed();
141 return httpClient.get<T>( 141 return httpClient.get<T>(
@@ -149,13 +149,13 @@ class GetConnect extends GetConnectInterface { @@ -149,13 +149,13 @@ class GetConnect extends GetConnectInterface {
149 149
150 @override 150 @override
151 Future<Response<T>> post<T>( 151 Future<Response<T>> post<T>(
152 - String url, 152 + String? url,
153 dynamic body, { 153 dynamic body, {
154 - String contentType,  
155 - Map<String, String> headers,  
156 - Map<String, dynamic> query,  
157 - Decoder<T> decoder,  
158 - Progress uploadProgress, 154 + String? contentType,
  155 + Map<String, String>? headers,
  156 + Map<String, dynamic>? query,
  157 + Decoder<T>? decoder,
  158 + Progress? uploadProgress,
159 }) { 159 }) {
160 _checkIfDisposed(); 160 _checkIfDisposed();
161 return httpClient.post<T>( 161 return httpClient.post<T>(
@@ -173,11 +173,11 @@ class GetConnect extends GetConnectInterface { @@ -173,11 +173,11 @@ class GetConnect extends GetConnectInterface {
173 Future<Response<T>> put<T>( 173 Future<Response<T>> put<T>(
174 String url, 174 String url,
175 dynamic body, { 175 dynamic body, {
176 - String contentType,  
177 - Map<String, String> headers,  
178 - Map<String, dynamic> query,  
179 - Decoder<T> decoder,  
180 - Progress uploadProgress, 176 + String? contentType,
  177 + Map<String, String>? headers,
  178 + Map<String, dynamic>? query,
  179 + Decoder<T>? decoder,
  180 + Progress? uploadProgress,
181 }) { 181 }) {
182 _checkIfDisposed(); 182 _checkIfDisposed();
183 return httpClient.put<T>( 183 return httpClient.put<T>(
@@ -195,11 +195,11 @@ class GetConnect extends GetConnectInterface { @@ -195,11 +195,11 @@ class GetConnect extends GetConnectInterface {
195 Future<Response<T>> patch<T>( 195 Future<Response<T>> patch<T>(
196 String url, 196 String url,
197 dynamic body, { 197 dynamic body, {
198 - String contentType,  
199 - Map<String, String> headers,  
200 - Map<String, dynamic> query,  
201 - Decoder<T> decoder,  
202 - Progress uploadProgress, 198 + String? contentType,
  199 + Map<String, String>? headers,
  200 + Map<String, dynamic>? query,
  201 + Decoder<T>? decoder,
  202 + Progress? uploadProgress,
203 }) { 203 }) {
204 _checkIfDisposed(); 204 _checkIfDisposed();
205 return httpClient.patch<T>( 205 return httpClient.patch<T>(
@@ -218,11 +218,11 @@ class GetConnect extends GetConnectInterface { @@ -218,11 +218,11 @@ class GetConnect extends GetConnectInterface {
218 String url, 218 String url,
219 String method, { 219 String method, {
220 dynamic body, 220 dynamic body,
221 - String contentType,  
222 - Map<String, String> headers,  
223 - Map<String, dynamic> query,  
224 - Decoder<T> decoder,  
225 - Progress uploadProgress, 221 + String? contentType,
  222 + Map<String, String>? headers,
  223 + Map<String, dynamic>? query,
  224 + Decoder<T>? decoder,
  225 + Progress? uploadProgress,
226 }) { 226 }) {
227 _checkIfDisposed(); 227 _checkIfDisposed();
228 return httpClient.request<T>( 228 return httpClient.request<T>(
@@ -240,10 +240,10 @@ class GetConnect extends GetConnectInterface { @@ -240,10 +240,10 @@ class GetConnect extends GetConnectInterface {
240 @override 240 @override
241 Future<Response<T>> delete<T>( 241 Future<Response<T>> delete<T>(
242 String url, { 242 String url, {
243 - Map<String, String> headers,  
244 - String contentType,  
245 - Map<String, dynamic> query,  
246 - Decoder<T> decoder, 243 + Map<String, String>? headers,
  244 + String? contentType,
  245 + Map<String, dynamic>? query,
  246 + Decoder<T>? decoder,
247 }) { 247 }) {
248 _checkIfDisposed(); 248 _checkIfDisposed();
249 return httpClient.delete( 249 return httpClient.delete(
@@ -262,14 +262,14 @@ class GetConnect extends GetConnectInterface { @@ -262,14 +262,14 @@ class GetConnect extends GetConnectInterface {
262 }) { 262 }) {
263 _checkIfDisposed(isHttp: false); 263 _checkIfDisposed(isHttp: false);
264 264
265 - final _socket = GetSocket(_concatUrl(url), ping: ping); 265 + final _socket = GetSocket(_concatUrl(url)!, ping: ping);
266 sockets.add(_socket); 266 sockets.add(_socket);
267 return _socket; 267 return _socket;
268 } 268 }
269 269
270 - String _concatUrl(String url) { 270 + String? _concatUrl(String? url) {
271 if (url == null) return baseUrl; 271 if (url == null) return baseUrl;
272 - return baseUrl == null ? url : baseUrl + url; 272 + return baseUrl == null ? url : baseUrl! + url;
273 } 273 }
274 274
275 /// query allow made GraphQL raw querys 275 /// query allow made GraphQL raw querys
@@ -294,9 +294,9 @@ class GetConnect extends GetConnectInterface { @@ -294,9 +294,9 @@ class GetConnect extends GetConnectInterface {
294 @override 294 @override
295 Future<GraphQLResponse<T>> query<T>( 295 Future<GraphQLResponse<T>> query<T>(
296 String query, { 296 String query, {
297 - String url,  
298 - Map<String, dynamic> variables,  
299 - Map<String, String> headers, 297 + String? url,
  298 + Map<String, dynamic>? variables,
  299 + Map<String, String>? headers,
300 }) async { 300 }) async {
301 try { 301 try {
302 final res = await post( 302 final res = await post(
@@ -316,7 +316,7 @@ class GetConnect extends GetConnectInterface { @@ -316,7 +316,7 @@ class GetConnect extends GetConnectInterface {
316 )) 316 ))
317 .toList()); 317 .toList());
318 } 318 }
319 - return GraphQLResponse<T>(body: res.body['data'] as T); 319 + return GraphQLResponse<T>(body: res.body['data'] as T?);
320 } on Exception catch (_) { 320 } on Exception catch (_) {
321 return GraphQLResponse<T>(graphQLErrors: [ 321 return GraphQLResponse<T>(graphQLErrors: [
322 GraphQLError( 322 GraphQLError(
@@ -330,9 +330,9 @@ class GetConnect extends GetConnectInterface { @@ -330,9 +330,9 @@ class GetConnect extends GetConnectInterface {
330 @override 330 @override
331 Future<GraphQLResponse<T>> mutation<T>( 331 Future<GraphQLResponse<T>> mutation<T>(
332 String mutation, { 332 String mutation, {
333 - String url,  
334 - Map<String, dynamic> variables,  
335 - Map<String, String> headers, 333 + String? url,
  334 + Map<String, dynamic>? variables,
  335 + Map<String, String>? headers,
336 }) async { 336 }) async {
337 try { 337 try {
338 final res = await post( 338 final res = await post(
@@ -352,7 +352,7 @@ class GetConnect extends GetConnectInterface { @@ -352,7 +352,7 @@ class GetConnect extends GetConnectInterface {
352 )) 352 ))
353 .toList()); 353 .toList());
354 } 354 }
355 - return GraphQLResponse<T>(body: res.body['data'] as T); 355 + return GraphQLResponse<T>(body: res.body['data'] as T?);
356 } on Exception catch (_) { 356 } on Exception catch (_) {
357 return GraphQLResponse<T>(graphQLErrors: [ 357 return GraphQLResponse<T>(graphQLErrors: [
358 GraphQLError( 358 GraphQLError(
1 class GetHttpException implements Exception { 1 class GetHttpException implements Exception {
2 final String message; 2 final String message;
3 3
4 - final Uri uri; 4 + final Uri? uri;
5 5
6 GetHttpException(this.message, [this.uri]); 6 GetHttpException(this.message, [this.uri]);
7 7
@@ -11,8 +11,8 @@ class GetHttpException implements Exception { @@ -11,8 +11,8 @@ class GetHttpException implements Exception {
11 11
12 class GraphQLError { 12 class GraphQLError {
13 GraphQLError({this.code, this.message}); 13 GraphQLError({this.code, this.message});
14 - final String message;  
15 - final String code; 14 + final String? message;
  15 + final String? code;
16 16
17 @override 17 @override
18 String toString() => 'GETCONNECT ERROR:\n\tcode:$code\n\tmessage:$message'; 18 String toString() => 'GETCONNECT ERROR:\n\tcode:$code\n\tmessage:$message';
1 import 'dart:async'; 1 import 'dart:async';
2 import 'dart:convert'; 2 import 'dart:convert';
3 -import 'package:flutter/foundation.dart';  
4 3
5 import '../src/certificates/certificates.dart'; 4 import '../src/certificates/certificates.dart';
6 import '../src/exceptions/exceptions.dart'; 5 import '../src/exceptions/exceptions.dart';
@@ -20,7 +19,7 @@ typedef Progress = Function(double percent); @@ -20,7 +19,7 @@ typedef Progress = Function(double percent);
20 19
21 class GetHttpClient { 20 class GetHttpClient {
22 String userAgent; 21 String userAgent;
23 - String baseUrl; 22 + String? baseUrl;
24 23
25 String defaultContentType = 'application/json; charset=utf-8'; 24 String defaultContentType = 'application/json; charset=utf-8';
26 25
@@ -28,7 +27,7 @@ class GetHttpClient { @@ -28,7 +27,7 @@ class GetHttpClient {
28 int maxRedirects; 27 int maxRedirects;
29 int maxAuthRetries; 28 int maxAuthRetries;
30 29
31 - Decoder defaultDecoder; 30 + Decoder? defaultDecoder;
32 31
33 Duration timeout; 32 Duration timeout;
34 33
@@ -46,7 +45,7 @@ class GetHttpClient { @@ -46,7 +45,7 @@ class GetHttpClient {
46 this.maxAuthRetries = 1, 45 this.maxAuthRetries = 1,
47 bool allowAutoSignedCert = false, 46 bool allowAutoSignedCert = false,
48 this.baseUrl, 47 this.baseUrl,
49 - List<TrustedCertificate> trustedCertificates, 48 + List<TrustedCertificate>? trustedCertificates,
50 }) : _httpClient = HttpRequestImpl( 49 }) : _httpClient = HttpRequestImpl(
51 allowAutoSignedCert: allowAutoSignedCert, 50 allowAutoSignedCert: allowAutoSignedCert,
52 trustedCertificates: trustedCertificates, 51 trustedCertificates: trustedCertificates,
@@ -73,11 +72,11 @@ class GetHttpClient { @@ -73,11 +72,11 @@ class GetHttpClient {
73 _modifier.removeResponseModifier<T>(interceptor); 72 _modifier.removeResponseModifier<T>(interceptor);
74 } 73 }
75 74
76 - Uri _createUri(String url, Map<String, dynamic> query) { 75 + Uri _createUri(String? url, Map<String, dynamic>? query) {
77 if (baseUrl != null) { 76 if (baseUrl != null) {
78 - url = baseUrl + url; 77 + url = baseUrl! + url!;
79 } 78 }
80 - final uri = Uri.parse(url); 79 + final uri = Uri.parse(url!);
81 if (query != null) { 80 if (query != null) {
82 return uri.replace(queryParameters: query); 81 return uri.replace(queryParameters: query);
83 } 82 }
@@ -85,16 +84,16 @@ class GetHttpClient { @@ -85,16 +84,16 @@ class GetHttpClient {
85 } 84 }
86 85
87 Future<Request<T>> _requestWithBody<T>( 86 Future<Request<T>> _requestWithBody<T>(
88 - String url,  
89 - String contentType, 87 + String? url,
  88 + String? contentType,
90 dynamic body, 89 dynamic body,
91 String method, 90 String method,
92 - Map<String, dynamic> query,  
93 - Decoder<T> decoder,  
94 - Progress uploadProgress, 91 + Map<String, dynamic>? query,
  92 + Decoder<T>? decoder,
  93 + Progress? uploadProgress,
95 ) async { 94 ) async {
96 - List<int> bodyBytes;  
97 - BodyBytesStream bodyStream; 95 + List<int>? bodyBytes;
  96 + Stream<List<int>>? bodyStream;
98 final headers = <String, String>{}; 97 final headers = <String, String>{};
99 98
100 headers['user-agent'] = userAgent; 99 headers['user-agent'] = userAgent;
@@ -139,16 +138,16 @@ class GetHttpClient { @@ -139,16 +138,16 @@ class GetHttpClient {
139 url: uri, 138 url: uri,
140 headers: headers, 139 headers: headers,
141 bodyBytes: bodyStream, 140 bodyBytes: bodyStream,
142 - contentLength: bodyBytes.length, 141 + contentLength: bodyBytes?.length ?? 0,
143 followRedirects: followRedirects, 142 followRedirects: followRedirects,
144 maxRedirects: maxRedirects, 143 maxRedirects: maxRedirects,
145 decoder: decoder, 144 decoder: decoder,
146 ); 145 );
147 } 146 }
148 147
149 - BodyBytesStream _trackProgress( 148 + Stream<List<int>> _trackProgress(
150 List<int> bodyBytes, 149 List<int> bodyBytes,
151 - Progress uploadProgress, 150 + Progress? uploadProgress,
152 ) { 151 ) {
153 var total = 0; 152 var total = 0;
154 var length = bodyBytes.length; 153 var length = bodyBytes.length;
@@ -164,12 +163,12 @@ class GetHttpClient { @@ -164,12 +163,12 @@ class GetHttpClient {
164 sink.add(data); 163 sink.add(data);
165 }), 164 }),
166 ); 165 );
167 - return BodyBytesStream(byteStream); 166 + return byteStream;
168 } 167 }
169 168
170 void _setSimpleHeaders( 169 void _setSimpleHeaders(
171 Map<String, String> headers, 170 Map<String, String> headers,
172 - String contentType, 171 + String? contentType,
173 ) { 172 ) {
174 headers['content-type'] = contentType ?? defaultContentType; 173 headers['content-type'] = contentType ?? defaultContentType;
175 headers['user-agent'] = userAgent; 174 headers['user-agent'] = userAgent;
@@ -179,7 +178,7 @@ class GetHttpClient { @@ -179,7 +178,7 @@ class GetHttpClient {
179 HandlerExecute<T> handler, { 178 HandlerExecute<T> handler, {
180 bool authenticate = false, 179 bool authenticate = false,
181 int requestNumber = 1, 180 int requestNumber = 1,
182 - Map<String, String> headers, 181 + Map<String, String>? headers,
183 }) async { 182 }) async {
184 try { 183 try {
185 var request = await handler(); 184 var request = await handler();
@@ -188,7 +187,7 @@ class GetHttpClient { @@ -188,7 +187,7 @@ class GetHttpClient {
188 request.headers[key] = value; 187 request.headers[key] = value;
189 }); 188 });
190 189
191 - if (authenticate) await _modifier.authenticator(request); 190 + if (authenticate) await _modifier.authenticator!(request);
192 await _modifier.modifyRequest(request); 191 await _modifier.modifyRequest(request);
193 192
194 var response = await _httpClient.send<T>(request); 193 var response = await _httpClient.send<T>(request);
@@ -238,9 +237,9 @@ class GetHttpClient { @@ -238,9 +237,9 @@ class GetHttpClient {
238 237
239 Future<Request<T>> _get<T>( 238 Future<Request<T>> _get<T>(
240 String url, 239 String url,
241 - String contentType,  
242 - Map<String, dynamic> query,  
243 - Decoder<T> decoder, 240 + String? contentType,
  241 + Map<String, dynamic>? query,
  242 + Decoder<T>? decoder,
244 ) { 243 ) {
245 final headers = <String, String>{}; 244 final headers = <String, String>{};
246 _setSimpleHeaders(headers, contentType); 245 _setSimpleHeaders(headers, contentType);
@@ -251,17 +250,18 @@ class GetHttpClient { @@ -251,17 +250,18 @@ class GetHttpClient {
251 url: uri, 250 url: uri,
252 headers: headers, 251 headers: headers,
253 decoder: decoder ?? (defaultDecoder as Decoder<T>), 252 decoder: decoder ?? (defaultDecoder as Decoder<T>),
  253 + contentLength: 0,
254 )); 254 ));
255 } 255 }
256 256
257 Future<Request<T>> _request<T>( 257 Future<Request<T>> _request<T>(
258 - String url, 258 + String? url,
259 String method, { 259 String method, {
260 - String contentType,  
261 - @required dynamic body,  
262 - @required Map<String, dynamic> query,  
263 - Decoder<T> decoder,  
264 - @required Progress uploadProgress, 260 + String? contentType,
  261 + required dynamic body,
  262 + required Map<String, dynamic>? query,
  263 + Decoder<T>? decoder,
  264 + required Progress? uploadProgress,
265 }) { 265 }) {
266 return _requestWithBody<T>( 266 return _requestWithBody<T>(
267 url, 267 url,
@@ -269,16 +269,16 @@ class GetHttpClient { @@ -269,16 +269,16 @@ class GetHttpClient {
269 body, 269 body,
270 method, 270 method,
271 query, 271 query,
272 - decoder ?? (defaultDecoder as Decoder<T>), 272 + decoder ?? (defaultDecoder as Decoder<T>?),
273 uploadProgress, 273 uploadProgress,
274 ); 274 );
275 } 275 }
276 276
277 Request<T> _delete<T>( 277 Request<T> _delete<T>(
278 String url, 278 String url,
279 - String contentType,  
280 - Map<String, dynamic> query,  
281 - Decoder<T> decoder, 279 + String? contentType,
  280 + Map<String, dynamic>? query,
  281 + Decoder<T>? decoder,
282 ) { 282 ) {
283 final headers = <String, String>{}; 283 final headers = <String, String>{};
284 _setSimpleHeaders(headers, contentType); 284 _setSimpleHeaders(headers, contentType);
@@ -288,18 +288,18 @@ class GetHttpClient { @@ -288,18 +288,18 @@ class GetHttpClient {
288 method: 'delete', 288 method: 'delete',
289 url: uri, 289 url: uri,
290 headers: headers, 290 headers: headers,
291 - decoder: decoder ?? (defaultDecoder as Decoder<T>), 291 + decoder: decoder ?? (defaultDecoder as Decoder<T>?),
292 ); 292 );
293 } 293 }
294 294
295 Future<Response<T>> patch<T>( 295 Future<Response<T>> patch<T>(
296 String url, { 296 String url, {
297 dynamic body, 297 dynamic body,
298 - String contentType,  
299 - Map<String, String> headers,  
300 - Map<String, dynamic> query,  
301 - Decoder<T> decoder,  
302 - Progress uploadProgress, 298 + String? contentType,
  299 + Map<String, String>? headers,
  300 + Map<String, dynamic>? query,
  301 + Decoder<T>? decoder,
  302 + Progress? uploadProgress,
303 // List<MultipartFile> files, 303 // List<MultipartFile> files,
304 }) async { 304 }) async {
305 try { 305 try {
@@ -327,13 +327,13 @@ class GetHttpClient { @@ -327,13 +327,13 @@ class GetHttpClient {
327 } 327 }
328 328
329 Future<Response<T>> post<T>( 329 Future<Response<T>> post<T>(
330 - String url, { 330 + String? url, {
331 dynamic body, 331 dynamic body,
332 - String contentType,  
333 - Map<String, String> headers,  
334 - Map<String, dynamic> query,  
335 - Decoder<T> decoder,  
336 - Progress uploadProgress, 332 + String? contentType,
  333 + Map<String, String>? headers,
  334 + Map<String, dynamic>? query,
  335 + Decoder<T>? decoder,
  336 + Progress? uploadProgress,
337 // List<MultipartFile> files, 337 // List<MultipartFile> files,
338 }) async { 338 }) async {
339 try { 339 try {
@@ -364,11 +364,11 @@ class GetHttpClient { @@ -364,11 +364,11 @@ class GetHttpClient {
364 String url, 364 String url,
365 String method, { 365 String method, {
366 dynamic body, 366 dynamic body,
367 - String contentType,  
368 - Map<String, String> headers,  
369 - Map<String, dynamic> query,  
370 - Decoder<T> decoder,  
371 - Progress uploadProgress, 367 + String? contentType,
  368 + Map<String, String>? headers,
  369 + Map<String, dynamic>? query,
  370 + Decoder<T>? decoder,
  371 + Progress? uploadProgress,
372 }) async { 372 }) async {
373 try { 373 try {
374 var response = await _performRequest<T>( 374 var response = await _performRequest<T>(
@@ -397,11 +397,11 @@ class GetHttpClient { @@ -397,11 +397,11 @@ class GetHttpClient {
397 Future<Response<T>> put<T>( 397 Future<Response<T>> put<T>(
398 String url, { 398 String url, {
399 dynamic body, 399 dynamic body,
400 - String contentType,  
401 - Map<String, String> headers,  
402 - Map<String, dynamic> query,  
403 - Decoder<T> decoder,  
404 - Progress uploadProgress, 400 + String? contentType,
  401 + Map<String, String>? headers,
  402 + Map<String, dynamic>? query,
  403 + Decoder<T>? decoder,
  404 + Progress? uploadProgress,
405 }) async { 405 }) async {
406 try { 406 try {
407 var response = await _performRequest<T>( 407 var response = await _performRequest<T>(
@@ -429,10 +429,10 @@ class GetHttpClient { @@ -429,10 +429,10 @@ class GetHttpClient {
429 429
430 Future<Response<T>> get<T>( 430 Future<Response<T>> get<T>(
431 String url, { 431 String url, {
432 - Map<String, String> headers,  
433 - String contentType,  
434 - Map<String, dynamic> query,  
435 - Decoder<T> decoder, 432 + Map<String, String>? headers,
  433 + String? contentType,
  434 + Map<String, dynamic>? query,
  435 + Decoder<T>? decoder,
436 }) async { 436 }) async {
437 try { 437 try {
438 var response = await _performRequest<T>( 438 var response = await _performRequest<T>(
@@ -513,10 +513,10 @@ class GetHttpClient { @@ -513,10 +513,10 @@ class GetHttpClient {
513 513
514 Future<Response<T>> delete<T>( 514 Future<Response<T>> delete<T>(
515 String url, { 515 String url, {
516 - Map<String, String> headers,  
517 - String contentType,  
518 - Map<String, dynamic> query,  
519 - Decoder<T> decoder, 516 + Map<String, String>? headers,
  517 + String? contentType,
  518 + Map<String, dynamic>? query,
  519 + Decoder<T>? decoder,
520 }) async { 520 }) async {
521 try { 521 try {
522 var response = await _performRequest<T>( 522 var response = await _performRequest<T>(