Stefan de Vogelaere

Merge remote-tracking branch 'upstream/master'

Showing 100 changed files with 899 additions and 2591 deletions

Too many changes to show.

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

... ... @@ -6,6 +6,7 @@ labels: ''
assignees: jonataslaw
---
**ATTENTION: DO NOT USE THIS FIELD TO ASK SUPPORT QUESTIONS. USE THE PLATFORM CHANNELS FOR THIS. THIS SPACE IS DEDICATED ONLY FOR BUGS DESCRIPTION.**
**Fill in the template. Issues that do not respect the model will be closed.**
**Describe the bug**
... ... @@ -27,8 +28,8 @@ If applicable, add screenshots to help explain your problem.
**Flutter Version:**
Enter the version of the Flutter you are using
**Get Version:**
Enter the version of the Get you are using
**Getx Version:**
Enter the version of the Getx you are using
**Describe on which device you found the bug:**
ex: Moto z2 - Android.
... ...
... ... @@ -6,6 +6,7 @@ labels: ''
assignees: ''
---
**ATTENTION: DO NOT USE THIS FIELD TO ASK SUPPORT QUESTIONS. USE THE PLATFORM CHANNELS FOR THIS. THIS SPACE IS DEDICATED ONLY FOR FEATURE REQUESTS**
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
... ...
... ... @@ -17,11 +17,10 @@ jobs:
# https://github.com/marketplace/actions/flutter-action
- uses: subosito/flutter-action@v1
with:
flutter-version: '1.17.1'
flutter-version: '1.20.2'
channel: 'stable'
- run: flutter pub get
# run static analys code
#- run: flutter analyze
- run: flutter analyze
# run flutter widgets tests and unit tests
- run: flutter test --coverage
# Upload coverage reports to Codecov
... ...
# See https://www.dartlang.org/guides/libraries/private-files
# See https://www.dartlang.org/guides/libraries/private-files
# Files and directories created by pub
.dart_tool/
.packages
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
.pub/
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
... ... @@ -25,3 +28,49 @@ example/android/
example/ios/
example/.dart_tool/
example/.packages
# IntelliJ
*.iml
.idea/*
#.idea/workspace.xml
#.idea/tasks.xml
#.idea/gradle.xml
#.idea/assetWizardSettings.xml
#.idea/dictionaries
#.idea/libraries
#.idea/caches
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/dictionaries
.idea/**/shelf
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
### https://raw.github.com/github/gitignore/80a8803b004013d17291196825a327b9e871f009/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
... ...
## [3.10.1]
- Fix analyzer
## [3.10.0]
Getx 3.10 released with CLI and Get Server.
- Added: analyser + effective dart (@Grohden)
- Added TextStyle to generalDialog title and message (@roipeker)
- renamed and added defaults transition duration and types in "GetInterface" (@roipeker)
- added missing parameters in Get.to/Get.offAll (@roipeker)
- added optional transitionDuration and transitionCurve to Get.dialog() (@roipeker)
- Changed HashMap<int,GetStateUpdate> to HashSet<GetStateUpdate> and allow update IDs groups on GetBuilder (@roipeker)
- Added a internal VoidCallback in GetStateUpdaterMixin::getUpdate (@roipeker)
- Added Curve property to routes (@roipeker)
- Improve docs, code cleanup, new GetStateUpdaterMixin and GetStateUpdate in favour of StateSetter on GetxController, GetBuilder, SimpleBuilder. (@roipeker)
- Added RxBool.toggle() as an easy shortcut for switching true/false values. (@roipeker)
- Added _RxImp.nil() to easily set the value to null (@roipeker)
- Added missing docs to Rx classes. (@roipeker)
- Added Get.delete(force:false) to Get extensions (@roipeker)
- Added Docs and comments (@nipodemos)
- Added docs to PT-br and fix typos (@eduardoflorence)
- Cleanup route code (@justkawal)
- Extension to facilitate insert widgets inside a CustomScrollView (@alexkharech)
- Fix docs .obs examples (@kai-oswald)
- Added tag capability to GetView
- Improve code separation of RouteManagement and Internacionalization
## [3.8.0]
- Added: Snackbar Status: Open, Opening, Closing and Closed
example:
```dart
Get.snackbar('title', 'message', snackbarStatus: (status) {
if (status == SnackbarStatus.CLOSED) {
// made anything
}
});
```
## [3.7.0]
- Added: RxSet. Sets can now also be reactive.
- Added isDesktop/isMobile (@roipeker)
- Improve GetPlatform: It is now possible to know which device the user is using if GetPlatform.isWeb is true.
context.responsiveValue used device orientation based on web and non-web applications. Now it checks if it is a desktop application (web or desktop application) to do the responsiveness calculation. (@roipeker)
- Change: The documentation previously stated that Iterables should not access the ".value" property.
However, many users did not pay attention to this fact, and ended up generating unnecessary issues and bugs in their application.
In this version, we focus on code security. Now ".value" is protected, so it cannot be accessed externally by Lists, Maps or Sets.
- Change: Observable lists are now Dart Lists.
There is no difference in your use:
`RxList list = [].obs;`
And you use
`List list = [].obs;`
- Change: You do not need to access the ".value" property of primitives.
For Strings you need interpolation.
For num, int, double, you will have the normal operators, and use it as dart types.
This way, `.value` can be used exclusively in ModelClasses.
Example:
```dart
var name = "Jonny" .obs;
// usage:
Text ("$name");
var count = 0.obs;
// usage:
increment() => count ++;
Text("$count");
```
Thus: List, Map, Set, num, int, double and String, as of this release, will no longer use the .value property.
NOTE:
The changes were not break changes, however, you may have missed the details of the documentation, so if you faced the message: "The member 'value' can only be used within instance members of subclasses of 'rx_list.dart' "you just need to remove the" .value "property from your list, and everything will work as planned.
The same goes for Maps and Sets.
## [3.6.2]
- Fix more formatting issues
## [3.6.1]
- Fix formatting issues
## [3.6.0]
- Added RxSet
- Change default logger to developer.log (@jorgegaticav)
- Added BindingsBuilder, ValueBuilder, and ObxValue (@roipeker)
- Fix fallback locale not working if missing country code (@thaihuynhxyz)
- Fix validation of email ".com.br"
## [3.5.1]
- Remove unnecessary whitespaces
## [3.5.0]
- Added logwritter (@stefandevo)
- Added responsiveValue (@juanjoseleca)
- Fixed ghost url for snackbar, bottomsheets, and dialogs and unnamed navigation.
## [3.4.6]
- Fix TextField dispose throw on last Flutter hotfix
... ... @@ -6,7 +100,8 @@
- Remove initialization console print
## [3.4.4]
- Fix exception 'isInit called null' when tags are used in conjunction with dependencies. (@djade007)
- Fix exception 'isInit called null' when tags are used in conjunction with dependencies. (@djade007)
- Fix typos (@tiagocpeixoto)
## [3.4.3]
- Fix onInit fired only first time
... ...
... ... @@ -4,61 +4,68 @@
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![Gitter](https://badges.gitter.im/flutter_get/community.svg)](https://gitter.im/flutter_get/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx)
[![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
<a href="https://github.com/Solido/awesome-flutter">
<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" 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>
![](getx.png)
<h3>We are sorry for the inconsistency in the translation. The GetX package is updated quite often and translations to docs may not come as fast. So in order for this documentation still has all content, i'll leave here all new untranslated texts (I consider is better to have the english docs then to not have at all), so if anyone wants to translate, it would be very helpful 😁</h3>
<h3>Lamentamos la inconsistencia en la traducción. El paquete GetX se actualiza con bastante frecuencia y es posible que las traducciones a documentos no sean tan rápidas. Entonces, para que esta documentación aún tenga todo el contenido, dejaré aquí todos los textos nuevos sin traducir (considero que es mejor tener los documentos en inglés que no tenerlos), por lo que si alguien quiere traducir, sería de gran ayuda 😁</h3>
- [Communication and support channels:](#communication-and-support-channels)
- [Sobre GetX](#sobre-getx)
- [Como contribuir](#como-contribuir)
- [Installing](#installing)
- [Proyeto Counter no GetX](#proyeto-counter-no-getx)
- [Instalando](#installing)
- [Proyecto Counter en GetX](#proyeto-counter-no-getx)
- [Los tres pilares](#los-tres-pilares)
- [Gestión del Estado](#gestión-del-estado)
- [Reactivo STATE_MANAGER](#reactivo-state_manager)
- [STATE_MANAGER Reactivo](#reactivo-state_manager)
- [Más detalles sobre la gestión del estado.](#más-detalles-sobre-la-gestión-del-estado)
- [Video explanation about state management](#video-explanation-about-state-management)
- [Explicación en video sobre state management](#video-explanation-about-state-management)
- [Gestión de Rutas](#gestión-de-rutas)
- [Más detalles sobre la gestión de rutas.](#más-detalles-sobre-la-gestión-de-rutas)
- [Video Explanation](#video-explanation)
- [Explicación del video](#video-explanation)
- [Gestión de dependencias](#gestión-de-dependencias)
- [Más detalles sobre la gestión de dependencias.](#más-detalles-sobre-la-gestión-de-dependencias)
- [Utils](#utils)
- [Utilidades](#utils)
- [Cambiar de tema](#cambiar-de-tema)
- [Otras API avanzadas y configuraciones manuales](#otras-api-avanzadas-y-configuraciones-manuales)
- [Configuraciones globales opcionales](#configuraciones-globales-opcionales)
- [Video explanation of Other GetX Features](#video-explanation-of-other-getx-features)
- [Explicación en video de Other GetX Features](#video-explanation-of-other-getx-features)
- [Rompiendo cambios desde 2.0](#rompiendo-cambios-desde-20)
- [¿Por qué Getx?](#por-qué-getx)
# Communication and support channels:
[**Slack (English)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Slack (Inglés)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Discord (English and Portuguese)**](https://discord.com/invite/9Y3wK9)
[**Discord (Ingles y Portugués)**](https://discord.com/invite/9Y3wK9)
[**Telegram (Portuguese)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
[**Telegram (Portugués)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
# Sobre GetX
- GetX es una solución extra ligera y potente para Flutter. Combina gestión de estádo de alto rendimiento, inyección de dependencia inteligente y gestión de rutas, de forma rápida y práctica.
- GetX es una solución extra ligera y potente para Flutter. Combina gestión de estádo de alto rendimiento, inyección de dependencia inteligente y gestión de rutas, de forma rápida y práctica.
- GetX no es para todos, se enfoca en el consumo mínimo de recursos (rendimiento) ([Mira los puntos de referencia](https://github.com/jonataslaw/benchmarks)), usando una sintaxis fácil y agradable (productividad), que permite el desacoplamiento total de la vista y la lógica de negocio (organización).
- GetX tiene 3 principios básicos, esto significa que esta es la prioridad para todos los recursos de la biblioteca.
**PERFORMANCE:** GetX se centra en el rendimiento y el consumo mínimo de recursos. Los puntos de referencia casi siempre no son importantes en el mundo real, pero si lo desea, aquí hay un indicador de consumo.([benchmarks](https://github.com/jonataslaw/benchmarks)), donde GetX lo hace mejor que otros enfoques de gestión estatal, por ejemplo. La diferencia no es grande, pero muestra nuestra preocupación por no desperdiciar sus recursos.
**PRODUCTIVITY:** GetX utiliza una sintaxis fácil y agradable.
**ORGANIZATION:** GetX permite el desacoplamiento total de la vista de la lógica empresarial.
- GetX permite ahorrar horas de desarrollo, extraer el máximo rendimiento de una aplicación, siendo tatno fácil de implementar para principiantes como precisa para expertos. Navegue sin contexto, abra dialogs, snackbars y bottomsheets desde cualquier parte de su código, gestione estados e inyecte dependencias de una manera fácil y práctica. GetX es seguro, estable, actualizado y ofrece una amplia gama de APIs que no están presentes en el framework por defecto.
* GetX ahorrará horas de desarrollo y extraerá el máximo rendimiento que su aplicación puede ofrecer, siendo fácil para los principiantes y precisa para los expertos. Navega sin contexto, abre diálogos, snackbars o bottomsheets desde cualquier lugar de tu código, gestiona estados e inyecta dependencias de forma fácil y práctica. Get es seguro, estable, actualizado y ofrece una amplia gama de API que no están presentes en el marco predeterminado.
- Tiene una multitud de funciones que le permiten comenzar a programar sin preocuparse por nada. Cada una de estas funciones se encuentra en contenedores separados y solo se inicia después de su uso. Si solo usa State Management, solo State Management se compilará. Si solo usa rutas, no se compilará nada de gestión de estado. Puede compilar el repositorio de referencia, y verá que usando solo la gestión de estado de GetX, la aplicación compilada se ha vuelto más pequeña que todas las demás aplicaciones de otros paquetes que solo tienen la gestión de estado, porque nada de lo que no se use se compilará en su código, y cada solución GetX fue diseñada para ser extra liviana. El mérito aquí también proviene del AOT de Flutter, que es increíble y logra eliminar los recursos no utilizados como ningún otro framework lo hace.
- GetX no es bloated. Tiene una multitud de características que le permiten comenzar a programar sin preocuparse por nada, pero cada una de estas características se encuentran en contenedores separados y solo se inician después de su uso. Si solo usa State Management, solo se compilará State Management. Si solo usa rutas, no se compilará nada de la administración estatal. Puede compilar el repositorio de referencia y verá que al usar solo la administración de estado de Get, la aplicación compilada con Get se ha vuelto más pequeña que todas las demás aplicaciones que solo tienen la administración de estado de otros paquetes, porque nada que no se use se compilará en su código, y cada solución GetX fue diseñada para ser muy liviana. El mérito aquí también proviene del movimiento del árbol de Flutter, que es increíble y logra eliminar los recursos no utilizados como ningún otro marco lo hace.
**GetX hace que su desarrollo sea productivo, pero ¿quiere hacerlo aún más productivo? [Agregue la extensión a su VSCode](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets)**
# Como contribuir
*¿Quieres contribuir al proyecto? Estaremos orgullosos de destacarte como uno de nuestros colaboradores. Aquí hay algunos puntos en los que puede contribuir y hacer que GetX (y Flutter) sea aún mejor.*
_¿Quieres contribuir al proyecto? Estaremos orgullosos de destacarte como uno de nuestros colaboradores. Aquí hay algunos puntos en los que puede contribuir y hacer que GetX (y Flutter) sea aún mejor._
- Ayudando a traducir el archivo Léame a otros idiomas.
... ... @@ -79,15 +86,15 @@ dependencies:
get:
```
Import get in files that it will be used:
Importar archivos get que se utilizarán:
```dart
import 'package:get/get.dart';
```
# Proyeto Counter no GetX
# Proyecto Counter no GetX
Vea una explicación más detallada de la administración del estado [aquí](./docs/es_ES/state_management.md). Allí verá más ejemplos y también la diferencia entre el Gestión del Estado simple y el Gestión del Estado reactivo
Vea una explicación más detallada de la administración del estado [aquí](./documentation/es_ES/state_management.md). Allí verá más ejemplos y también la diferencia entre el Gestión del Estado simple y el Gestión del Estado reactivo
El proyecto "contador" creado por defecto en un nuevo proyecto en Flutter tiene más de 100 líneas (con comentarios). Para mostrar el poder de GetX, demostraré cómo hacer un "contador" cambiando el estado con cada clic, cambiando de página y compartiendo el estado entre pantallas, todo de manera organizada, separando la vista de la lógica de negocio, SOLO 26 LÍNEAS DE CÓDIGO INCLUIDOS COMENTARIOS.
... ... @@ -100,10 +107,10 @@ void main() => runApp(GetMaterialApp(home: Home()));
**Nota**: esto no modifica el MaterialApp del Flutter, GetMaterialApp no es una MaterialApp modificado, es solo un Widget preconfigurado, que tiene como child un MaterialApp por defecto. Puede configurar esto manualmente, pero definitivamente no es necesario. GetMaterialApp creará rutas, las inyectará, inyectará traducciones, inyectará todo lo que necesita para la navegación de rutas. Si usa Get solo para la gestión de estado o dependencias, no es necesario usar GetMaterialApp. GetMaterialApp es necesario para rutas, snackbars, internacionalización, bottomSheets, diálogos y APIs de alto nivel relacionadas con rutas y ausencia de contexto.
**Note²:** This step in only necessary if you gonna use route management (`Get.to()`, `Get.back()` and so on). If you not gonna use it then it is not necessary to do step 1
**Note²:** Este paso solo es necesario si vas a usar route management (`Get.to()`, `Get.back()` y así). Si no lo va a usar, no es necesario que realice el paso 1
- Paso 2:
Cree su clase con la lógica de negocio colocando todas las variables, métodos y controladores dentro de ella. Puede hacer que cualquier variable sea observable usando un simple ".obs".
Cree su clase con la lógica de negocio colocando todas las variables, métodos y controladores dentro de ella. Puede hacer que cualquier variable sea observable usando un simple ".obs".
```dart
class Controller extends GetxController {
... ... @@ -113,20 +120,20 @@ class Controller extends GetxController {
```
- Paso 3:
Cree su vista, use StatelessWidget y ahorre algo de RAM, con GetX ya no necesitará usar StatefulWidget.
Cree su vista, use StatelessWidget y ahorre algo de RAM, con GetX ya no necesitará usar StatefulWidget.
```dart
class Home extends StatelessWidget {
// Instantiate your class using Get.put() to make it available for all "child" routes there.
// Cree una instancia de su clase usando Get.put() para que esté disponible para todas las rutas "secundarias" allí.
final Controller c = Get.put(Controller());
@override
Widget build(context) => Scaffold(
// Use Obx(()=> to update Text() whenever count is changed.
// Utilice Obx(()=> para actualizar Text() siempre que se cambie el recuento.
appBar: AppBar(title: Obx(() => Text("Clicks: " + c.count.string))),
// Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
// Reemplace el Navigator.push de 8 líneas por un simple Get.to(). No necesitas contexto
body: Center(child: RaisedButton(
child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
floatingActionButton:
... ... @@ -134,12 +141,12 @@ class Home extends StatelessWidget {
}
class Other extends StatelessWidget {
// You can ask Get to find a Controller that is being used by another page and redirect you to it.
// Puede pedirle a Get que busque un controlador que está siendo utilizado por otra página y le redirija a él.
final Controller c = Get.find();
@override
Widget build(context){
// Access the updated count variable
// Acceder a la variable de recuento actualizada
return Scaffold(body: Center(child: Text(c.count.string)));
}
}
... ... @@ -188,14 +195,13 @@ Obx(() => Text (controller.name));
### Más detalles sobre la gestión del estado.
**Vea una explicación más detallada de la administración del estado [aquí](./docs/es_ES/state_management.md). Allí verá más ejemplos y también la diferencia entre el Gestión del Estado simple y el Gestión del Estado reactivo**
### Video explanation about state management
**Vea una explicación más detallada de la administración del estado [aquí](./documentation/es_ES/state_management.md). Allí verá más ejemplos y también la diferencia entre el Gestión del Estado simple y el Gestión del Estado reactivo**
### Explicación en video sobre state management
Amateur Coder did an awesome video about state management! Link: [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw)
Darwin Morocho hizo una increíble serie de videos sobre state management! Link: [Complete GetX State Management](https://www.youtube.com/watch?v=PTjj0DFK8BA&list=PLV0nOzdUS5XtParoZLgKoVwNSK9zROwuO)
You will get a good idea of GetX power.
Obtendrá una buena idea de la potencia de GetX.
## Gestión de Rutas
... ... @@ -231,11 +237,11 @@ var data = await Get.to(Payment());
### Más detalles sobre la gestión de rutas.
**Vea una explicación más detallada de la Gestión de Rutas [aquí](./docs/es_ES/route_management.md).**
**Vea una explicación más detallada de la Gestión de Rutas [aquí](./documentation/es_ES/route_management.md).**
### Video Explanation
### Explicación del video
Amateur Coder did an excellent video that cover route management with Get! here is the link: [Complete Getx Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI)
Amateur Coder hizo un excelente video que cubre route management con Get! aquí esta el link: [Complete Getx Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI)
## Gestión de dependencias
... ... @@ -253,11 +259,11 @@ En lugar de crear una instancia de su clase dentro de la clase que está utiliza
controller.fetchApi();
```
Imagine que ha navegado a través de numerosas rutas y necesita datos que quedaron en su controlador, necesitaría un gestor de estado combinado con Providere o Get_it, ¿correcto? No con GetX. Solo necesita pedirle a GetX que "encuentre" su controlador, no necesita dependencias adicionales:
Imagine que ha navegado a través de numerosas rutas y necesita datos que quedaron en su controlador, necesitaría un gestor de estado combinado con Provider o Get_it, ¿correcto? No con GetX. Solo necesita pedirle a GetX que "encuentre" su controlador, no necesita dependencias adicionales:
```dart
Controller controller = Get.find();
//Yes, it looks like Magic, Get will find your controller, and will deliver it to you. You can have 1 million controllers instantiated, Get will always give you the right controller.
//Sí, parece que es magia, Get encontrará su controlador y se lo entregará. Puede tener 1 millón de controladores instanciados, Get siempre le dará el controlador correcto.
```
Y luego podrá recuperar los datos de su controlador que se obtuvieron allí:
... ... @@ -270,20 +276,20 @@ Text(controller.textFromApi);
```dart
Get.lazyPut<Service>(()=> ApiMock());
/// ApiMock will only be called when someone uses Get.find<Service> for the first time
/// ApiMock solo se llamará cuando alguien use Get.find<Service> por primera vez
```
### Más detalles sobre la gestión de dependencias.
**Vea una explicación más detallada de la Gestión de dependencias [aquí](./docs/es_ES/dependency_management.md).**
**Vea una explicación más detallada de la Gestión de dependencias [aquí](./documentation/es_ES/dependency_management.md).**
# Utils
# Utilidades
## Cambiar de tema
No utilice ningún widget de nivel superior que GetMaterialApp para actualizarlo. Esto puede activar claves duplicadas. Mucha gente está acostumbrada al enfoque prehistórico de crear un widget "ThemeProvider" solo para cambiar el tema de su aplicación, y esto definitivamente NO es necesario con GetX.
Puede crear su tema personalizado y simplemente agregarlo dentro de Get.changeTheme sin ningun boilerplate para eso:
Puede crear su tema personalizado y simplemente agregarlo dentro de Get.changeTheme sin ningún boilerplate para eso:
```dart
Get.changeTheme(ThemeData.light());
... ... @@ -322,116 +328,116 @@ MaterialApp(
```
```dart
// give the current args from currentScreen
// dar los argumentos actuales de currentScreen
Get.arguments
// give arguments of previous route
// dar argumentos de la ruta anterior
Get.previousArguments
// give name of previous route
// dar el nombre de la ruta anterior
Get.previousRoute
// give the raw route to access for example, rawRoute.isFirst()
// dar la ruta sin procesar para acceder, por ejemplo, rawRoute.isFirst()
Get.rawRoute
// give access to Rounting API from GetObserver
// dar acceso a Routing API desde GetObserver
Get.routing
// check if snackbar is open
// comprobar si la cafetería está abierta
Get.isSnackbarOpen
// check if dialog is open
// comprobar si el diálogo está abierto
Get.isDialogOpen
// check if bottomsheet is open
// comprobar si bottomsheet está abierto
Get.isBottomSheetOpen
// remove one route.
// eliminar una ruta.
Get.removeRoute()
// back repeatedly until the predicate returns true.
// volver repetidamente hasta que predicate devuelva verdadero.
Get.until()
// go to next route and remove all the previous routes until the predicate returns true.
//ir a la siguiente ruta y eliminar todas las rutas anteriores hasta que predicate devuelva verdadero.
Get.offUntil()
// go to next named route and remove all the previous routes until the predicate returns true.
// ir a la siguiente ruta con nombre y eliminar todas las rutas anteriores hasta que predicate devuelve verdadero.
Get.offNamedUntil()
//Check in what platform the app is running
//Verifique en qué plataforma se ejecuta la aplicación
GetPlatform.isAndroid
GetPlatform.isIOS
GetPlatform.isWeb
// Equivalent to the method: MediaQuery.of(context).size.height, but they are immutable.
// Equivalente al método: MediaQuery.of(context).size.height, pero son inmutables.
Get.height
Get.width
// Gives the context of the screen in the foreground anywhere in your code.
// Da el contexto de la pantalla en primer plano en cualquier parte de su código.
Get.context
// Gives the context of the snackbar/dialog/bottomsheet in the foreground anywhere in your code.
// Da el contexto de la barra de bocadillos / diálogo / hoja inferior en primer plano en cualquier parte de su código.
Get.contextOverlay
// Note: the following methods are extensions on context. Since you
// have access to context in any place of your UI, you can use it anywhere in the UI code
// Note: los siguientes métodos son extensiones de context. Desde que tu
// tiene acceso al contexto en cualquier lugar de su interfaz de usuario, puede usarlo en cualquier lugar del código de la interfaz de usuario
// If you need a changeable height/width (like browser windows that can be scaled) you will need to use context.
// Si necesita un cambiable height/width (como las ventanas del navegador que se pueden escalar) necesitará usar context.
context.width
context.height
// gives you the power to define half the screen now, a third of it and so on.
//Useful for responsive applications.
// le da el poder de definir la mitad de la pantalla ahora, un tercio y así sucesivamente.
// Útil para aplicaciones receptivas.
// param dividedBy (double) optional - default: 1
// param reducedBy (double) optional - default: 0
context.heightTransformer()
context.widthTransformer()
/// similar to MediaQuery.of(context).size
/// Similar a MediaQuery.of(context).size
context.mediaQuerySize()
/// similar to MediaQuery.of(context).padding
/// similar a MediaQuery.of(context).padding
context.mediaQueryPadding()
/// similar to MediaQuery.of(context).viewPadding
/// similar a MediaQuery.of(context).viewPadding
context.mediaQueryViewPadding()
/// similar to MediaQuery.of(context).viewInsets;
/// similar a MediaQuery.of(context).viewInsets;
context.mediaQueryViewInsets()
/// similar to MediaQuery.of(context).orientation;
/// similar a MediaQuery.of(context).orientation;
context.orientation()
/// check if device is on landscape mode
/// comprobar si el dispositivo esta en landscape mode
context.isLandscape()
/// check if device is on portrait mode
/// comprobar si el dispositivo esta en portrait mode
context.isPortrait()
/// similar to MediaQuery.of(context).devicePixelRatio;
/// similar a MediaQuery.of(context).devicePixelRatio;
context.devicePixelRatio()
/// similar to MediaQuery.of(context).textScaleFactor;
/// similar a MediaQuery.of(context).textScaleFactor;
context.textScaleFactor()
/// get the shortestSide from screen
/// obtener el lado más corto de la pantalla
context.mediaQueryShortestSide()
/// True if width be larger than 800
/// Verdadero si el ancho es mayor que 800
context.showNavbar()
/// True if the shortestSide is smaller than 600p
/// Verdadero si el lado más corto es menor que 600p
context.isPhone()
/// True if the shortestSide is largest than 600p
/// Verdadero si el lado más corto es más grande que 600p
context.isSmallTablet()
/// True if the shortestSide is largest than 720p
/// Verdadero si el lado más corto es mayor que 720p
context.isLargeTablet()
/// True if the current device is Tablet
/// Verdadero si el dispositivo actual es una tableta
context.isTablet()
```
... ... @@ -456,10 +462,26 @@ Get.config(
)
```
## Video explanation of Other GetX Features
Opcionalmente, puede redirigir todos los mensajes de registro de Get. Si desea utilizar su propio paquete de registro favorito y desea capturar los registros allí.
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// pase el mensaje a su paquete de registro favorito aquí
//Nota: incluso si los mensajes de registro están desactivados
// con el comando "enableLog: false", los mensajes seguirán pasando por aquí
// Debe verificar esta configuración manualmente aquí si desea respetarla
}
```
## Video explanation of Other GetX Features
Amateur Coder did an awesome video about utils, storage, bindings and other features! Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
Amateur Coder hizo un video asombroso sobre utilidades, almacenamiento, enlaces y otras características! Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
# Rompiendo cambios desde 2.0
... ... @@ -469,7 +491,7 @@ Antes: StringX ahora: RxString
Antes: IntX ahora: RxInt
Antes: MapX ahora: RxMax
Antes: MapX ahora: RxMap
Antes: ListX ahora: RxList
... ... @@ -496,7 +518,7 @@ Ahora:
```dart
GetMaterialApp(
getPages: [
GetPage(name: '/', page:()=> Home()),
GetPage(name: '/', page: () => Home()),
]
)
```
... ... @@ -512,7 +534,7 @@ GetStorage box = GetStorage();
GetMaterialApp(
getPages: [
GetPage(name: '/', page:(){
GetPage(name: '/', page:(){
return box.hasData('token') ? Home() : Login();
})
]
... ... @@ -521,13 +543,13 @@ GetMaterialApp(
# ¿Por qué Getx?
1- Después de una actualización de Flutter, muchos paquetes suelen romperse. A veces se producen errores de compilación, errores de los que aún no hay respuestas y el desarrollador necesita saber el origen del error, poder rastrearlo, y solo entonces intentar abrir un issue en el repositorio correspondiente, para finalmente ver su problema resuelto. Getx centraliza los principales recursos para el desarrollo (gestión de estado, dependencia y rutas), lo que le permite agregar un único paquete a su pubspec y comenzar a trabajar. Después de una actualización de Flutter, lo único que debe hacer es actualizar la dependencia Get y ponerse a trabajar. Get también resuelve problemas de compatibilidad. ¿Cuántas veces una versión de un paquete no es compatible con la versión de otro, porque una usa una dependencia en una versión y la otra en otra? Tampoco es una preocupación usando Get, ya que todo estará en el mismo paquete y será totalmente compatible.
1- Después de una actualización de Flutter, muchos paquetes suelen romperse. A veces se producen errores de compilación, errores de los que aún no hay respuestas y el desarrollador necesita saber el origen del error, poder rastrear, y solo entonces intentar abrir un issue en el repositorio correspondiente, para finalmente ver su problema resuelto. Getx centraliza los principales recursos para el desarrollo (gestión de estado, dependencia y rutas), lo que le permite agregar un único paquete a su pubspec y comenzar a trabajar. Después de una actualización de Flutter, lo único que debe hacer es actualizar la dependencia Get y ponerse a trabajar. Get también resuelve problemas de compatibilidad. ¿Cuántas veces una versión de un paquete no es compatible con la versión de otro, porque una usa una dependencia en una versión y la otra en otra? Tampoco es una preocupación usando Get, ya que todo estará en el mismo paquete y será totalmente compatible.
2- Flutter es fácil, Flutter es increíble, pero todavía tiene algo repetitivo que puede ser no deseado para la mayoría de los desarrolladores, como `Navigator.of(context).push (context, bulder [...]`. Get simplifica el desarrollo. En lugar de escribir 8 líneas de código para simplemente llamar a una ruta, simplemente puede hacerlo: `Get.to(Home())` y listo, irá a la página siguiente. Algo doloroso de hacer con Flutter actualmente, mientras que con GetX es estúpidamente simple. Gestionar estados en Flutter y dependencias también es algo que genera mucho debate, ya que hay cientos de patrones en el pub. Pero no hay nada tan fácil como agregar un ".obs" al final de su variable, y colocar su widget dentro de un Obx, y eso es todo, todas las actualizaciones de esa variable se actualizarán automáticamente en la pantalla.
2- Flutter es fácil, Flutter es increíble, pero todavía tiene algo repetitivo que puede ser no deseado para la mayoría de los desarrolladores, como `Navigator.of(context).push (context, builder [...]`. Get simplifica el desarrollo. En lugar de escribir 8 líneas de código para simplemente llamar a una ruta, simplemente puede hacerlo: `Get.to(Home())` y listo, irá a la página siguiente. Algo doloroso de hacer con Flutter actualmente, mientras que con GetX es estúpidamente simple. Gestionar estados en Flutter y dependencias también es algo que genera mucho debate, ya que hay cientos de patrones en el pub. Pero no hay nada tan fácil como agregar un ".obs" al final de su variable, y colocar su widget dentro de un Obx, y eso es todo, todas las actualizaciones de esa variable se actualizarán automáticamente en la pantalla.
3- Facilidad sin preocuparse por el rendimiento. El rendimiento de Flutter ya es sorprendente, pero imagine que usa un gestor de estado y un localizador para distribuir sus clases de bloc/stores/controllers/ etc. Tendrá que llamar manualmente a la exclusión de esa dependencia cuando no la necesite. Pero, ¿alguna vez pensó en simplemente usar el controlador, y cuando ya no sea necesario, simplemente se elimine de la memoria? Eso es lo que hace GetX. Con SmartManagement, todo lo que no se está utilizando se elimina de la memoria, y no debería tener que preocuparse por nada más que la programación. Se le garantiza el consumo mínimo de recursos, sin siquiera haber creado una lógica para esto.
4- Desacoplamiento real. Es posible que haya escuchado la idea de "separar la vista de la lógica de negocio". Esta no es una peculiaridad de BLoC,MVC,MVVM, cualquier otro estándar en el mercado tiene este concepto. Sin embargo, a menudo se puede mitigar en Flutter debido al uso del contexto.
4- Desacoplamiento real. Es posible que haya escuchado la idea de "separar la vista de la lógica de negocio". Esta no es una peculiaridad de BLoC, MVC, MVVM, cualquier otro estándar en el mercado tiene este concepto. Sin embargo, a menudo se puede mitigar en Flutter debido al uso del contexto.
Si necesita contexto para encontrar un InheritedWidget, lo necesita en la vista o pasado por parámetro. En particular, encuentro esta solución muy fea, y para trabajar en equipo siempre tendremos una dependencia de la lógica de negocios de la vista. Getx no es ortodoxo con el enfoque estándar, y aunque no prohíbe completamente el uso de StatefulWidgets, InitState, etc., siempre tiene un enfoque similar que puede ser más limpio. Los controladores tienen ciclos de vida, y cuando necesita hacer una solicitud API REST, por ejemplo, no depende de nada en la vista. Puede usar onInit para iniciar la llamada http, y cuando lleguen los datos, se rellenarán las variables. Como GetX es completamente reactivo (realmente, y funciona bajo streams), una vez que se llenan los elementos, todos los widgets que usan esa variable se actualizarán automáticamente en la vista. Esto permite que las personas con experiencia en IU trabajen solo con widgets y no tengan que enviar nada a la lógica de negocios que no sean eventos de usuario (como hacer clic en un botón), mientras que las personas que trabajan con lógica de negocios podrán crearla y probarla por separado.
Esta librería siempre se actualizará e implementará nuevas características. Siéntase libre de ofrecer PRs y contribuir a ellas.
... ...
... ... @@ -4,7 +4,10 @@
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![Gitter](https://badges.gitter.im/flutter_get/community.svg)](https://gitter.im/flutter_get/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx)
[![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
<a href="https://github.com/Solido/awesome-flutter">
<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
</a>
... ... @@ -12,7 +15,6 @@
![](getx.png)
- [Communication and support channels:](#communication-and-support-channels)
- [About Get](#about-get)
- [Installing](#installing)
- [Counter App with GetX](#counter-app-with-getx)
... ... @@ -28,39 +30,39 @@
- [More details about dependency management](#more-details-about-dependency-management)
- [How to contribute](#how-to-contribute)
- [Utils](#utils)
- [Internationalization](#internationalization)
- [Change Theme](#change-theme)
- [Other Advanced APIs](#other-advanced-apis)
- [Optional Global Settings and Manual configurations](#optional-global-settings-and-manual-configurations)
- [Video explanation of Other GetX Features](#video-explanation-of-other-getx-features)
- [Video explanation of Other GetX Features](#video-explanation-of-other-getx-features)
- [Breaking changes from 2.0](#breaking-changes-from-20)
- [Why Getx?](#why-getx)
# Communication and support channels:
[**Slack (English)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Discord (English and Portuguese)**](https://discord.com/invite/9Hpt99N)
[**Telegram (Portuguese)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
# About Get
- GetX is an extra-light and powerful solution for Flutter. It combines high performance state management, intelligent dependency injection, and route management in a quick and practical way.
- GetX has 3 basic principles, this means that this is the priority for all resources in the library
**PERFORMANCE:** GetX is focused on performance and minimum consumption of resources. Benchmarks are almost always not important in the real world, but if you want, there is a consumption indicator here([benchmarks](https://github.com/jonataslaw/benchmarks)), where GetX does better than other state management approaches, for example. The difference is not large, but it shows our concern not to waste its resources.
**PRODUCTIVITY:** GetX uses an easy and pleasant syntax.
**ORGANIZATION:** GetX allows total decoupling of the View from the business logic.
- **PERFORMANCE:** GetX is focused on performance and minimum consumption of resources. Benchmarks are almost always not important in the real world, but if you want, there is a consumption indicator here([benchmarks](https://github.com/jonataslaw/benchmarks)), where GetX does better than other state management approaches, for example. The difference is not large, but it shows our concern not to waste its resources.
- **PRODUCTIVITY:** GetX uses an easy and pleasant syntax. No matter what you want to do, there is always an easier way with Getx. It will save hours of development, and will extract the maximum performance that your application can deliver
- **ORGANIZATION:** GetX allows the total decoupling of the View, presentation logic, business logic, dependency injection, and navigation. You do not need context to navigate between routes, so you are not dependent on the widget tree (visualization) for this. You don't need context to access your controllers / blocks through an inheritedWidget, so you completely decouple your presentation logic and business logic from your visualization layer. You do not need to inject your Controllers/Models/Blocs classes into your widget tree through multiproviders, for this GetX uses its own dependency injection feature, decoupling the DI from its view completely.
With GetX you know where to find each feature of your application, having clean code by default. This in addition to facilitating maintenance, makes the sharing of modules, something that until then in Flutter was unthinkable, something totally possible.
BLoC was a starting point for organizing code in Flutter, it separates business logic from visualization. Getx is a natural evolution of this, not only separating the business logic, but the presentation logic. Bonus injection of dependencies and routes are also decoupled, and the data layer is out of it all. You know where everything is, and all of this in an easier way than building a hello world.
GetX is the easiest, most practical and scalable way to build high-performance applications with the Flutter SDK, with a large ecosystem around it that works perfectly together, being easy for beginners, and accurate for experts. It is secure, stable, up-to-date, and offers a huge range of APIs build-in that are not present on default Flutter SDK.
- GetX is not a bloated. It has a multitude of features that allow you to start programming without worrying about anything, but each of these features are in separate containers, and are only started after use. If you only use State Management, only State Management will be compiled. If you only use routes, nothing from the state management will be compiled. You can compile the benchmark repository, and you will see that using only Get state management, the application compiled with Get has become smaller than all other applications that have only the state management of other packages, because nothing that is not used will be compiled into your code, and each GetX solution was designed to be extra lightweight. The merit here also comes from Flutter's tree shaking which is incredible, and manages to eliminate unused resources like no other framework does.
- GetX will save hours of development, and will extract the maximum performance that your application can deliver, being easy for beginners, and accurate for experts. Navigate without context, open dialogs, snackbars or bottomsheets from anywhere in your code, Manage states and inject dependencies in an easy and practical way. Get is secure, stable, up-to-date, and offers a huge range of APIs that are not present on default framework.
**GetX has an [extension to VSCode](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) to make your programming with GetX even more productive**
**GetX Community channels:**
- GetX is not a bloated. It has a multitude of features that allow you to start programming without worrying about anything, but each of these features are in separate containers, and are only started after use. If you only use State Management, only State Management will be compiled. If you only use routes, nothing from the state management will be compiled. You can compile the benchmark repository, and you will see that using only Get state management, the application compiled with Get has become smaller than all other applications that have only the state management of other packages, because nothing that is not used will be compiled into your code, and each GetX solution was designed to be extra lightweight. The merit here also comes from Flutter's tree shaking which is incredible, and manages to eliminate unused resources like no other framework does.
GetX has a highly active and helpful community. If you have questions, or would like any assistance regarding the use of this framework, please join our community channels, your question will be answered more quickly, and it will be the most suitable place. This repository is exclusive for opening issues, and requesting resources, but feel free to be part of GetX Community.
**GetX makes your development productive, but want to make it even more productive? Add the extension [GetX extension to VSCode](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) to your VSCode**
| **Slack** | **Discord** | **Telegram** |
| --------- | ------------| ------------ |
| [![Get on 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) |
# Installing
... ... @@ -81,7 +83,7 @@ import 'package:get/get.dart';
The "counter" project created by default on new project on Flutter has over 100 lines (with comments). To show the power of Get, I will demonstrate how to make a "counter" changing the state with each click, switching between pages and sharing the state between screens, all in an organized way, separating the business logic from the view, in ONLY 26 LINES CODE INCLUDING COMMENTS.
- Step 1:
Add "Get" before your materialApp, turning it into GetMaterialApp
Add "Get" before your MaterialApp, turning it into GetMaterialApp
```dart
void main() => runApp(GetMaterialApp(home: Home()));
... ... @@ -97,7 +99,7 @@ You can make any variable observable using a simple ".obs".
```dart
class Controller extends GetxController{
var count = 0.obs;
increment() => count.value++;
increment() => count+1;
}
```
... ... @@ -113,7 +115,7 @@ class Home extends StatelessWidget {
@override
Widget build(context) => Scaffold(
// Use Obx(()=> to update Text() whenever count is changed.
appBar: AppBar(title: Obx(() => Text("Clicks: " + c.count.string))),
appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),
// Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
body: Center(child: RaisedButton(
... ... @@ -129,7 +131,7 @@ class Other extends StatelessWidget {
@override
Widget build(context){
// Access the updated count variable
return Scaffold(body: Center(child: Text(c.count.string)));
return Scaffold(body: Center(child: Text("${c.count}")));
}
}
```
... ... @@ -184,14 +186,14 @@ var name = 'Jonatas Borges'.obs;
And in the UI, when you want to show that value and update the screen whenever tha values changes, simply do this:
```dart
Obx (() => Text (controller.name));
Obx(() => Text("${controller.name}"));
```
That's all. It's *that* simple.
### More details about state management
**See an more in-depth explanation of state management [here](./docs/en_US/state_management.md). There you will see more examples and also the difference between the simple stage manager and the reactive state manager**
**See an more in-depth explanation of state management [here](./documentation/en_US/state_management.md). There you will see more examples and also the difference between the simple stage manager and the reactive state manager**
### Video explanation about state management
... ... @@ -240,7 +242,7 @@ Noticed that you didn't had to use context to do any of these things? That's one
### More details about route management
**Get work with named routes and also offer a lower level control over your routes! There is a in-depth documentation [here](./docs/en_US/route_management.md)**
**Get work with named routes and also offer a lower level control over your routes! There is a in-depth documentation [here](./documentation/en_US/route_management.md)**
### Video Explanation
... ... @@ -281,7 +283,7 @@ Text(controller.textFromApi);
### More details about dependency management
**See a more in-depth explanation of dependency management [here](./docs/en_US/dependency_management.md)**
**See a more in-depth explanation of dependency management [here](./documentation/en_US/dependency_management.md)**
# How to contribute
... ... @@ -296,26 +298,82 @@ Text(controller.textFromApi);
Any contribution is welcome!
# Utils
## Internationalization
### Translations
Translations are kept as a simple key-value dictionary map.
To add custom translations, create a class and extend `Translations`.
```dart
import 'package:get/get.dart';
class Messages extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'en_US': {
'hello': 'Hello World',
},
'de_DE': {
'hello': 'Hallo Welt',
}
};
}
```
#### Using translations
Just append `.tr` to the specified key and it will be translated, using the current value of `Get.locale` and `Get.fallbackLocale`.
```dart
Text('title'.tr);
```
### Locales
Pass parameters to `GetMaterialApp` to define the locale and translations.
```dart
return GetMaterialApp(
translations: Messages(), // your translations
locale: Locale('en', 'US'), // translations will be displayed in that locale
fallbackLocale: Locale('en', 'UK'), // specify the fallback locale in case an invalid locale is selected.
supportedLocales: <Locale>[Locale('en', 'UK'), Locale('en', 'US'), Locale('de','DE')] // specify the supported locales
);
```
#### Change locale
Call `Get.updateLocale(locale)` to update the locale. Translations then automatically use the new locale.
```dart
var locale = Locale('en', 'US');
Get.updateLocale(locale);
```
#### System locale
To read the system locale, you could use `window.locale`.
```dart
import 'dart:ui' as ui;
return GetMaterialApp(
locale: ui.window.locale,
);
```
## Change Theme
Please do not use any higher level widget than GetMaterialApp in order to update it. This can trigger duplicate keys. A lot of people are used to the prehistoric approach of creating a "ThemeProvider" widget just to change the theme of your app, and this is definitely NOT necessary with Get.
Please do not use any higher level widget than `GetMaterialApp` in order to update it. This can trigger duplicate keys. A lot of people are used to the prehistoric approach of creating a "ThemeProvider" widget just to change the theme of your app, and this is definitely NOT necessary with **GetX™**.
You can create your custom theme and simply add it within Get.changeTheme without any boilerplate for that:
You can create your custom theme and simply add it within `Get.changeTheme` without any boilerplate for that:
```dart
Get.changeTheme(ThemeData.light());
```
If you want to create something like a button that changes the theme with onTap, you can combine two Get APIs for that, the api that checks if the dark theme is being used, and the theme change API, you can just put this within an onPressed:
If you want to create something like a button that changes the Theme in `onTap`, you can combine two **GetX™** APIs for that:
- The api that checks if the dark `Theme` is being used.
- And the `Theme` Change API, you can just put this within an `onPressed`:
```dart
Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());
```
When darkmode is activated, it will switch to the light theme, and when the light theme is activated, it will change to dark.
When `.darkmode` is activated, it will switch to the _light theme_, and when the _light theme_ becomes active, it will change to _dark theme_.
If you want to know in depth how to change the theme, you can follow this tutorial on Medium that even teaches the persistence of the theme using Get:
If you want to know in depth how to change the Theme, you can follow this tutorial on Medium which even teaches the persistence of the theme using **GetX™**:
- [Dynamic Themes in 3 lines using Get](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Tutorial by [Rod Brown](https://github.com/RodBr).
... ... @@ -361,60 +419,73 @@ Get.offNamedUntil()
//Check in what platform the app is running
GetPlatform.isAndroid
GetPlatform.isIOS
GetPlatform.isMacOS
GetPlatform.isWindows
GetPlatform.isLinux
GetPlatform.isFuchsia
//Check the device type
GetPlatform.isMobile
GetPlatform.isDesktop
//All platforms are supported independently in web!
//You can tell if you are running inside a browser
//on Windows, iOS, OSX, Android, etc.
GetPlatform.isWeb
// Equivalent to the method: MediaQuery.of(context).size.height, but they are immutable.
// Equivalent to : MediaQuery.of(context).size.height,
// but immutable.
Get.height
Get.width
// Gives the current context of navigator.
// Gives the current context of the Navigator.
Get.context
// Gives the context of the snackbar/dialog/bottomsheet in the foreground anywhere in your code.
// Gives the context of the snackbar/dialog/bottomsheet in the foreground, anywhere in your code.
Get.contextOverlay
// Note: the following methods are extensions on context. Since you
// have access to context in any place of your UI, you can use it anywhere in the UI code
// If you need a changeable height/width (like browser windows that can be scaled) you will need to use context.
// If you need a changeable height/width (like Desktop or browser windows that can be scaled) you will need to use context.
context.width
context.height
// gives you the power to define half the screen now, a third of it and so on.
//Useful for responsive applications.
// Gives you the power to define half the screen, a third of it and so on.
// Useful for responsive applications.
// param dividedBy (double) optional - default: 1
// param reducedBy (double) optional - default: 0
context.heightTransformer()
context.widthTransformer()
/// similar to MediaQuery.of(context).size
/// Similar to MediaQuery.of(context).size
context.mediaQuerySize()
/// similar to MediaQuery.of(context).padding
/// Similar to MediaQuery.of(context).padding
context.mediaQueryPadding()
/// similar to MediaQuery.of(context).viewPadding
/// Similar to MediaQuery.of(context).viewPadding
context.mediaQueryViewPadding()
/// similar to MediaQuery.of(context).viewInsets;
/// Similar to MediaQuery.of(context).viewInsets;
context.mediaQueryViewInsets()
/// similar to MediaQuery.of(context).orientation;
/// Similar to MediaQuery.of(context).orientation;
context.orientation()
/// check if device is on landscape mode
/// Check if device is on landscape mode
context.isLandscape()
/// check if device is on portrait mode
/// Check if device is on portrait mode
context.isPortrait()
/// similar to MediaQuery.of(context).devicePixelRatio;
/// Similar to MediaQuery.of(context).devicePixelRatio;
context.devicePixelRatio()
/// similar to MediaQuery.of(context).textScaleFactor;
/// Similar to MediaQuery.of(context).textScaleFactor;
context.textScaleFactor()
/// get the shortestSide from screen
/// Get the shortestSide from screen
context.mediaQueryShortestSide()
/// True if width be larger than 800
... ... @@ -431,6 +502,14 @@ context.isLargeTablet()
/// True if the current device is Tablet
context.isTablet()
/// Returns a value<T> according to the screen size
/// can give value for:
/// watch: if the shortestSide is smaller than 300
/// mobile: if the shortestSide is smaller than 600
/// tablet: if the shortestSide is smaller than 1200
/// desktop: if width is largest than 1200
context.responsiveValue<T>()
```
### Optional Global Settings and Manual configurations
... ... @@ -444,7 +523,7 @@ MaterialApp(
);
```
You will also be able to use your own Middleware within GetObserver, this will not influence anything.
You will also be able to use your own Middleware within `GetObserver`, this will not influence anything.
```dart
MaterialApp(
... ... @@ -455,7 +534,8 @@ MaterialApp(
);
```
You can create Global settings for Get. Just add Get.config to your code before pushing any route or do it directly in your GetMaterialApp
You can create _Global Settings_ for `Get`. Just add `Get.config` to your code before pushing any route.
Or do it directly in your `GetMaterialApp`
```dart
GetMaterialApp(
... ... @@ -474,7 +554,9 @@ Get.config(
)
```
You can optionally redirect all the logging messages from Get. If you want to use your own favourite logging package and want to capture the logs there.
You can optionally redirect all the logging messages from `Get`.
If you want to use your own, favourite logging package,
and want to capture the logs there:
```dart
GetMaterialApp(
... ... @@ -490,6 +572,251 @@ void localLogWriter(String text, {bool isError = false}) {
```
### Local State Widgets
These Widgets allows you to manage a single value, and keep the state ephemeral and locally.
We have flavours for Reactive and Simple.
For instance, you might use them to toggle obscureText in a `TextField`, maybe create a custom
Expandable Panel, or maybe modify the current index in `BottomNavigationBar` while changing the content
of the body in a `Scaffold`.
#### ValueBuilder
A simplification of `StatefulWidget` that works with a `.setState` callback that takes the updated value.
```dart
ValueBuilder<bool>(
initialValue: false,
builder: (value, updateFn) => Switch(
value: value,
onChanged: updateFn, // same signature! you could use ( newValue ) => updateFn( newValue )
),
// if you need to call something outside the builder method.
onUpdate: (value) => print("Value updated: $value"),
onDispose: () => print("Widget unmounted"),
),
```
#### ObxValue
Similar to [`ValueBuilder`](#valuebuilder), but this is the Reactive version, you pass a Rx instance (remember the magical .obs?) and
updates automatically... isn't it awesome?
```dart
ObxValue((data) => Switch(
value: data.value,
onChanged: data, // Rx has a _callable_ function! You could use (flag) => data.value = flag,
),
false.obs,
),
```
## Useful tips
`.obs`ervables (also known as _Rx_ Types) have a wide variety of internal methods and operators.
> Is very common to _believe_ that a property with `.obs` **IS** the actual value... but make no mistake!
We avoid the Type declaration of the variable, because Dart's compiler is smart enough, and the code
looks cleaner, but:
```dart
var message = 'Hello world'.obs;
print( 'Message "$message" has Type ${message.runtimeType}');
```
Even if `message` _prints_ the actual String value, the Type is **RxString**!
So, you can't do `message.substring( 0, 4 )`.
You have to access the real `value` inside the _observable_:
The most "used way" is `.value`, but, did you know that you can also use...
```dart
final name = 'GetX'.obs;
// only "updates" the stream, if the value is different from the current one.
name.value = 'Hey';
// this weird (and kinda cool) assignment, updates the stream no matter what
// it takes nulls, or same value... but rebuilds the observers.
name << 'Hey'; // !
// All Rx properties are "callable" and returns the new value.
// but this approach does not accepts `null`, the UI will not rebuild.
name('Hello');
// is like a getter, prints 'Hello'.
name() ;
/// numbers:
final count = 0.obs;
// you can just most basic operators acts on the property!
count + 1;
// Watch out! this is only valid if `count` is not final, but var
count += 1;
// You can also compare against values:
count > 2;
/// booleans:
final flag = false.obs;
// switches the value between true/false
flag.toggle();
/// all types:
// Sets the `value` to null.
flag.nil();
// All toString(), toJson() operations are passed down to the `value`
print( count ); // calls `toString()` inside for RxInt
final abc = [0,1,2].obs;
// Converts the value to a json Array, prints RxList
// Json is supported by all Rx types!
print('json: ${jsonEncode(abc)}, type: ${abc.runtimeType}');
// RxMap, RxList and RxSet are special Rx types, that extends their native types.
// but you can work with a List as a regular list, although is reactive!
abc.add(12); // pushes 12 to the list, and UPDATES the stream.
abc[3]; // like Lists, reads the index 3.
// equality works with the Rx and the value, but hashCode is always taken from the value
final number = 12.obs;
print( number == 12 ); // prints > true
/// Custom Rx Models:
// toJson(), toString() are deferred to the child, so you can implement override on them, and print() the observable directly.
class User {
String name, last;
int age;
User({this.name, this.last, this.age});
@override
String toString() => '$name $last, $age years old';
}
final user = User(name: 'John', last: 'Doe', age: 33).obs;
// `user` is "reactive", but the properties inside ARE NOT!
// So, if we change some variable inside of it...
user.value.name = 'Roi';
// The widget will not rebuild!,
// `Rx` don't have any clue when you change something inside user.
// So, for custom classes, we need to manually "notify" the change.
user.refresh();
// or we can use the `update()` method!
user.update((value){
value.name='Roi';
});
print( user );
// this also works.
user << user.value;
```
#### GetView
I love this Widget, is so simple, yet, so useful!
Is a `const Stateless` Widget that has a getter `controller` for a registered `Controller`, that's all.
```dart
class AwesomeController extends GetxController {
final String title = 'My Awesome View';
}
// ALWAYS remember to pass the `Type` you used to register your controller!
class AwesomeView extends GetView<AwesomeController> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(20),
child: Text( controller.title ), // just call `controller.something`
);
}
}
```
#### GetWidget
Most people have no idea about this Widget, or totally confuse the usage of it.
The use case is very rare, but very specific: It `caches` a Controller.
Because of the _cache_, can't be a `const Stateless`.
> So, when do you need to "cache" a Controller?
If you use, another "not so common" feature of **GetX**: `Get.create()`.
`Get.create(()=>Controller())` will generate a new `Controller` each time you call
`Get.find<Controller>()`,
That's where `GetWidget` shines... as you can use it, for example,
to keep a list of Todo items. So, if the widget gets "rebuilt", it will keep the same controller instance.
#### GetxService
This class is like a `GetxController`, it shares the same lifecycle ( `onInit()`, `onReady()`, `onClose()`).
But has no "logic" inside of it. It just notifies **GetX** Dependency Injection system, that this subclass
**can not** be removed from memory.
So is super useful to keep your "Services" always reachable and active with `Get.find()`. Like:
`ApiService`, `StorageService`, `CacheService`.
```dart
Future<void> main() async {
await initServices(); /// AWAIT SERVICES INITIALIZATION.
runApp(SomeApp());
}
/// Is a smart move to make your Services intiialize before you run the Flutter app.
/// as you can control the execution flow (maybe you need to load some Theme configuration,
/// apiKey, language defined by the User... so load SettingService before running ApiService.
/// so GetMaterialApp() doesnt have to rebuild, and takes the values directly.
void initServices() async {
print('starting services ...');
/// Here is where you put get_storage, hive, shared_pref initialization.
/// or moor connection, or whatever that's async.
await Get.putAsync(() => DbService().init());
await Get.putAsync(SettingsService()).init();
print('All services started...');
}
class DbService extends GetxService {
Future<DbService> init() async {
print('$runtimeType delays 2 sec');
await 2.delay();
print('$runtimeType ready!');
return this;
}
}
class SettingsService extends GetxService {
void init() async {
print('$runtimeType delays 1 sec');
await 1.delay();
print('$runtimeType ready!');
}
}
```
The only way to actually delete a `GetxService`, is with `Get.reset()` which is like a
"Hot Reboot" of your app. So remember, if you need absolute persistance of a class instance during the
lifetime of your app, use `GetxService`.
## Video explanation of Other GetX Features
... ... @@ -527,7 +854,7 @@ Now:
```dart
GetMaterialApp(
getPages: [
GetPage(name: '/', page:()=> Home()),
GetPage(name: '/', page: () => Home()),
]
)
```
... ...
... ... @@ -4,12 +4,16 @@
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![Gitter](https://badges.gitter.im/flutter_get/community.svg)](https://gitter.im/flutter_get/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx)
[![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
<a href="https://github.com/Solido/awesome-flutter">
<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" 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>
![](getx.png)
- [Kanały komunikacji i wsparcia:](#kanały-komunikacji-i-wsparcia)
... ... @@ -176,7 +180,7 @@ Obx (() => Text (controller.name));
To wszystko. *Proste*, co nie?
### Bardziej szczegółowo o menadżerze stanu
**Zobacz bardziej szczegółowe wytłumaczenie menadz=żera sranu [tutaj](./docs/en_US/state_management.md). Znajdują się tam przykłady jak o różnice między prostym menadżerem stanu oraz reaktywnym**
**Zobacz bardziej szczegółowe wytłumaczenie menadz=żera sranu [tutaj](./documentation/en_US/state_management.md). Znajdują się tam przykłady jak o różnice między prostym menadżerem stanu oraz reaktywnym**
### Video tłumaczące użycie menadżera stanu
... ... @@ -237,7 +241,7 @@ Zobacz, ze do żadnej z tych operacji nie potrzebowałeś contextu. Jest to jedn
### Więcej o routach
**Get używa named routes i także oferuje niskopoziomową obsługę routów! Zobacz bardziej szczegółową dokumentacje [tutaj](./docs/en_US/route_management.md)**
**Get używa named routes i także oferuje niskopoziomową obsługę routów! Zobacz bardziej szczegółową dokumentacje [tutaj](./documentation/en_US/route_management.md)**
### Video tłumaczące użycie
... ... @@ -274,7 +278,7 @@ Text(controller.textFromApi);
```
### Bardziej szczegółowo o menadżerze dependencies
**Zobzcz więcej w dokumentacji [tutaj](./docs/en_US/dependency_management.md)**
**Zobzcz więcej w dokumentacji [tutaj](./documentation/en_US/dependency_management.md)**
# Jak włożyć coś od siebie
... ... @@ -466,6 +470,19 @@ Get.config(
)
```
Opcjonalnie możesz przekierować wszystkie logi z Get by używać swojej ulubionej paczki i zbierać w niej logi.
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// tutaj przekaż wiadomosci do ulubionej paczki
// pamiętaj że nawet jeśli "enableLog: false" logi i tak będą wysłane w tym callbacku
// Musisz sprawdzić konfiguracje flag jeśli chcesz przez GetConfig.isLogEnable
}
```
## Video tłumaczące inne funkcjonalności GetX
... ... @@ -505,7 +522,7 @@ Teraz:
```dart
GetMaterialApp(
getPages: [
GetPage(name: '/', page:()=> Home()),
GetPage(name: '/', page: () => Home()),
]
)
```
... ...
... ... @@ -4,12 +4,16 @@
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![Gitter](https://badges.gitter.im/flutter_get/community.svg)](https://gitter.im/flutter_get/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://communityinviter.com/apps/getxworkspace/getx)
[![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
<a href="https://github.com/Solido/awesome-flutter">
<img alt="Awesome Flutter" src="https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square" />
</a>
<a href="https://www.buymeacoffee.com/jonataslaw" target="_blank"><img src="https://i.imgur.com/aV6DDA7.png" alt="Buy Me A Coffee" 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>
![](getx.png)
<h2> Pedimos desculpas por qualquer parte não traduzida aqui. O GetX é atualizado com muita frequência e as traduções podem não vir ao mesmo tempo. Então, para manter essa documentação pelo menos com tudo que a versão em inglês tem, eu vou deixar todos os textos não-traduzidos aqui (eu considero que é melhor ele estar lá em inglês do que não estar), então se alguém quiser traduzir, seria muito útil 😁</h2>
... ... @@ -30,10 +34,11 @@
- [Mais detalhes sobre gerenciamento de dependências](#mais-detalhes-sobre-gerenciamento-de-dependências)
- [Como contribuir](#como-contribuir)
- [Utilidades](#utilidades)
- [Internacionalização](#internacionalização)
- [Mudar tema (changeTheme)](#mudar-tema-changetheme)
- [Outras APIs avançadas](#outras-apis-avançadas)
- [Configurações Globais opcionais e configurações manuais](#configurações-globais-opcionais-e-configurações-manuais)
- [Video explanation of Other GetX Features](#video-explanation-of-other-getx-features)
- [Video explanation of Other GetX Features](#explicação-em-vídeo-sobre-outras-features-do-getx)
- [Breaking Changes da versão 2 para 3](#breaking-changes-da-versão-2-para-3)
- [Tipagem Rx](#tipagem-rx)
- [RxController e GetBuilder se uniram](#rxcontroller-e-getbuilder-se-uniram)
... ... @@ -45,21 +50,21 @@
[**Slack (Inglês)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Discord (Inglês e Português)**](https://discord.com/invite/9Y3wK9)
[**Discord (Inglês e Português)**](https://discord.com/invite/9Hpt99N)
[**Telegram (Português)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
# Sobre Get
- Get é uma biblioteca poderosa e extra-leve para Flutter. Ela combina um gerenciador de estado de alta performance, injeção de dependência inteligente e gerenciamento de rotas de uma forma rápida e prática.
- Get é uma biblioteca poderosa e extraleve para Flutter. Ela combina um gerenciador de estado de alta performance, injeção de dependência inteligente e gerenciamento de rotas de uma forma rápida e prática.
- Get não é para todos, seu foco é:
- **Performance**: Já que gasta o mínimo de recursos
- **Produtividade**: Usando uma sintaxe fácil e agradável
- **Organização**: Que permite o total desacoplamento da View e da lógica de negócio.
- Get vai economizar horas de desenvolvimento, e vai extrair a performance máxima que sua aplicação pode entregar, enquanto é fácil para iniciantes e preciso para experts.
- Get vai economizar horas de desenvolvimento e vai extrair a performance máxima que sua aplicação pode entregar, enquanto é fácil para iniciantes e preciso para experts.
- Navegue por rotas sem `context`, abra `Dialog`s, `Snackbar`s ou `BottomSheet`s de qualquer lugar no código, gerencie estados e injete dependências de uma forma simples e prática.
- Get é seguro, estável, atualizado e oferece uma enorme gama de APIs que não estão presentes no framework padrão.
- GetX é desacoplado. Ele tem uma variedade de recursos que te permite começar a programar sem se preocupar com nada, mas cada um desses recursos estão em um container separado, ou seja, nenhuma depende da outra para funcionar. Elas só são inicializadas após o uso. Se você usa apenas o gerenciador de estado, apenas ele será compilado. Teste você mesmo, vá no repositório de benchmark do getX e perceberá: usando somente o gerenciador de estado do Get, a aplicação ficou mais leve do que outros projetos que também estão usando só o gerenciador de estado, porque nada que não seja usado será compilado no seu código, e cada recuro do GetX foi feito para ser muito leve. O mérito vem também do AOT do próprio Flutter que é incrível, e consegue eliminar recursos não utilizados de uma forma que nenhum outro framework consegue.
- GetX é desacoplado. Ele tem uma variedade de recursos que te permite começar a programar sem se preocupar com nada, mas cada um desses recursos estão em um container separado, ou seja, nenhuma depende da outra para funcionar. Elas só são inicializadas após o uso. Se você usa apenas o gerenciador de estado, apenas ele será compilado. Teste você mesmo, vá no repositório de benchmark do getX e perceberá: usando somente o gerenciador de estado do Get, a aplicação ficou mais leve do que outros projetos que também estão usando só o gerenciador de estado, porque nada que não seja usado será compilado no seu código e cada recuro do GetX foi feito para ser muito leve. O mérito vem também do AOT do próprio Flutter que é incrível e consegue eliminar recursos não utilizados de uma forma que nenhum outro framework consegue.
**GetX faz seu desenvolvimento mais produtivo, mas quer deixá-lo mais produtivo ainda? Adicione a extensão [GetX extension](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) no seu VSCode**. Não disponível para outras IDEs por enquanto.
... ... @@ -89,12 +94,12 @@ Troque `MaterialApp` para `GetMaterialApp`
void main() => runApp(GetMaterialApp(home: Home()));
```
- **Obs:** Isso não modifica o `MaterialApp` do Flutter, GetMaterialApp não é uma versão modificada do MaterialApp, é só um Widget pré-configurado, que tem como child o MaterialApp padrão. Você pode configurar isso manualmente, mas definitivamente não é necessário. GetMaterialApp vai criar rotas, injetá-las, injetar traduções, injetar tudo que você precisa para navegação por rotas (gerenciamento de rotas). Se você quer somente usar o gerenciadro de estado ou somente o gerenciador de dependências, não é necessário usar o GetMaterialApp. Ele somente é necessário para:
- **Obs:** Isso não modifica o `MaterialApp` do Flutter, GetMaterialApp não é uma versão modificada do MaterialApp, é só um Widget pré-configurado, que tem como child o MaterialApp padrão. Você pode configurar isso manualmente, mas definitivamente não é necessário. GetMaterialApp vai criar rotas, injetá-las, injetar traduções, injetar tudo que você precisa para navegação por rotas (gerenciamento de rotas). Se você quer somente usar o gerenciador de estado ou somente o gerenciador de dependências, não é necessário usar o GetMaterialApp. Ele somente é necessário para:
- Rotas
- Snackbars/bottomsheets/dialogs
- apis relacionadas a rotas e a ausência de `context`
- Internacionalização
- **Obs²:** Esse passo só é necessário se você for usar o gerenciamento de rotas (`Get,to()`, `Get.back()` e assim por diante), Se você não vai usar isso então não é necessário seguir o passo 1
- **Obs²:** Esse passo só é necessário se você for usar o gerenciamento de rotas (`Get.to()`, `Get.back()` e assim por diante), Se você não vai usar isso então não é necessário seguir o passo 1
- Passo 2:
Cria a sua classe de regra de negócio e coloque todas as variáveis, métodos e controllers dentro dela.
... ... @@ -159,7 +164,7 @@ Definitivamente, Get não é o inimigo de nenhum gerenciador, porque Get é um m
Programação reativa pode alienar muitas pessoas porque é dito que é complicado. GetX transforma a programação reativa em algo bem simples:
* Você não precisa de criar StreamControllers
* Você não precisa criar StreamControllers
* Você não precisa criar um StreamBuilder para cada variável
* Você não precisa criar uma classe para cada estado
* Você não precisa criar um get para o valor inicial
... ... @@ -191,7 +196,7 @@ Só isso. É *simples assim*;
### Mais detalhes sobre gerenciamento de estado
**Veja uma explicação mais completa do gerenciamento de estado [aqui](./docs/pt_BR/state_management.md). Lá terá mais exemplos e também a diferença do simple state manager do reactive state manager**
**Veja uma explicação mais completa do gerenciamento de estado [aqui](./documentation/pt_BR/state_management.md). Lá terá mais exemplos e também a diferença do simple state manager do reactive state manager**
### Explicação em video do gerenciamento de estado
... ... @@ -225,7 +230,7 @@ Para ir para a próxima tela e cancelar todas as rotas anteriores (útil em tela
Get.offAll(ProximaTela());
```
Para navegar para a próxima rota, e receber ou atualizar dados assim que retornar da rota:
Para navegar para a próxima rota e receber ou atualizar dados assim que retornar da rota:
```dart
var dados = await Get.to(Pagamento());
... ... @@ -235,7 +240,7 @@ Notou que você não precisou usar `context` para fazer nenhuma dessas coisas? E
### Mais detalhes sobre gerenciamento de rotas
**GetX funciona com rotas nomeadas também! Veja uma explicação mais completa do gerenciamento de rotas [aqui](./docs/pt_BR/route_management.md)**
**GetX funciona com rotas nomeadas também! Veja uma explicação mais completa do gerenciamento de rotas [aqui](./documentation/pt_BR/route_management.md)**
### Explicação em video do gerenciamento de rotas
... ... @@ -263,7 +268,7 @@ Agora, imagine que você navegou por inúmeras rotas e precisa de dados que fora
```dart
Controller controller = Get.find();
// Sim, parece Magia, o Get irá descobrir qual é seu controller, e irá te entregar.
// Sim, parece Magia, o Get irá descobrir qual é seu controller e irá te entregar.
// Você pode ter 1 milhão de controllers instanciados, o Get sempre te entregará o controller correto.
// Apenas se lembre de Tipar seu controller, final controller = Get.find(); por exemplo, não irá funcionar.
```
... ... @@ -274,7 +279,7 @@ E então você será capaz de recuperar os dados do seu controller que foram obt
Text(controller.textFromApi);
```
Procurando por `lazyLoading`?(carregar somente quando for usar) Você pode declarar todos os seus controllers, e eles só vão ser inicializados e chamados quando alguém precisar. Você pode fazer isso
Procurando por `lazyLoading` (carregar somente quando for usar)? Você pode declarar todos os seus controllers e eles só vão ser inicializados e chamados quando alguém precisar. Você pode fazer isso
```dart
Get.lazyPut<Service>(()=> ApiMock());
... ... @@ -283,7 +288,7 @@ Get.lazyPut<Service>(()=> ApiMock());
### Mais detalhes sobre gerenciamento de dependências
**Veja uma explicação mais completa do gerenciamento de dependência [aqui](./docs/pt_BR/dependency_management.md)**
**Veja uma explicação mais completa do gerenciamento de dependência [aqui](./documentation/pt_BR/dependency_management.md)**
# Como contribuir
... ... @@ -291,7 +296,7 @@ Quer contribuir no projeto? Nós ficaremos orgulhosos de ressaltar você como um
- Ajudando a traduzir o README para outras linguagens.
- Adicionando mais documentação ao README (até o momento, várias das funcionalidades do Get não foram documentadas).
- Fazendo artigos/vídeos ensinando a usar o Get (eles serão inseridos no README, e no futuro na nossa Wiki).
- Fazendo artigos/vídeos ensinando a usar o Get (eles serão inseridos no README e no futuro na nossa Wiki).
- Fazendo PR's (Pull-Requests) para código/testes.
- Incluindo novas funcionalidades.
... ... @@ -299,9 +304,64 @@ Qualquer contribuição é bem-vinda!
# Utilidades
## Internacionalização
### Traduções
As traduções são mantidas num simples dictionary map de chave-valor.
Para adicionar traduções personalizadas, crie uma classe e estenda `Translations`.
```dart
import 'package:get/get.dart';
class Messages extends Translations {
@override
Map<String, Map<String, String>> get keys => {
'en_US': {
'hello': 'Hello World',
},
'de_DE': {
'hello': 'Hallo Welt',
}
};
}
```
#### Usando traduções
Basta anexar `.tr` a chave especificada e ela será traduzida, usando o valor atual de `Get.locale` e `Get.fallbackLocale`.
```dart
Text('hello'.tr);
```
### Localidade
Passe parâmetros para `GetMaterialApp` definir a localidade e as traduções.
```dart
return GetMaterialApp(
translations: Messages(), // suas traduções
locale: Locale('en', 'US'), // as traduções serão exibidas para esta localidade
fallbackLocale: Locale('en', 'UK'), // especifica uma localidade em caso de falha na localidade definida
supportedLocales: <Locale>[Locale('en', 'UK'), Locale('en', 'US'), Locale('de','DE')] // especifica as localidades suportados
);
```
#### Alterar local
Use `Get.updateLocale(locale)` para atualizar a localidade. As traduções usarão automaticamente a nova localidade.
```dart
var locale = Locale('en', 'US');
Get.updateLocale(locale);
```
#### Localidade do sistema operacional
Para ler a localidade do sistema operacional, você pode usar `window.locale`.
```dart
import 'dart:ui' as ui;
return GetMaterialApp(
locale: ui.window.locale,
);
```
## Mudar tema (changeTheme)
Por favor não use widget acima do GetMaterialApp para atualizar o tome. Isso pode causar keys duplicadas. Várias pessoas estão acostumadas com o jeito normal de criar um Widget `ThemeProvider` só pra alterar o thema do app, mas isso definitivamente NÃO é necessário no Get.
Por favor não use widget acima do GetMaterialApp para atualizar o tema. Isso pode causar keys duplicadas. Várias pessoas estão acostumadas com o jeito normal de criar um Widget `ThemeProvider` só pra alterar o tema do app, mas isso definitivamente NÃO é necessário no Get.
Você pode criar seu tema customizado e simplesmente adicionar dentro do `Get.changeTheme` sem nenhum boilerplate para isso:
... ... @@ -319,7 +379,7 @@ Get.changeTheme(
)
```
Quando o modo Dark está ativado, ele vai trocar pro modo light, e vice versa.
Quando o modo Dark está ativado, ele vai trocar pro modo light e vice versa.
Se você quiser saber mais como trocar o tema, você pode seguir esse tutorial no Medium que até ensina persistência do tema usando Get (e SharedPreferences):
... ... @@ -390,47 +450,65 @@ Get.contextOverlay
context.width
context.height
/// similar to MediaQuery.of(this).padding
// Dá a você agora o poder de definir metade da tela, um terço da dela e assim por diante.
// Útil para aplicativos responsivos.
// param dividedBy (double) opcional - default: 1
// param reducedBy (double) opcional - default: 0
context.heightTransformer()
context.widthTransformer()
/// similar a MediaQuery.of(context).size
context.mediaQuerySize()
/// similar a MediaQuery.of(this).padding
context.mediaQueryPadding()
/// similar to MediaQuery.of(this).viewPadding
/// similar a MediaQuery.of(this).viewPadding
context.mediaQueryViewPadding()
/// similar to MediaQuery.of(this).viewInsets;
/// similar a MediaQuery.of(this).viewInsets;
context.mediaQueryViewInsets()
/// similar to MediaQuery.of(this).orientation;
/// similar a MediaQuery.of(this).orientation;
context.orientation()
/// check if device is on landscape mode
/// verifica se o dispositivo está no modo paisagem
context.isLandscape()
/// check if device is on portrait mode
/// verifica se o dispositivo está no modo retrato
context.isPortrait()
/// similar to MediaQuery.of(this).devicePixelRatio;
/// similar a MediaQuery.of(this).devicePixelRatio;
context.devicePixelRatio()
/// similar to MediaQuery.of(this).textScaleFactor;
/// similar a MediaQuery.of(this).textScaleFactor;
context.textScaleFactor()
/// get the shortestSide from screen
/// obtém a menor dimensão (largura ou altura) da tela
context.mediaQueryShortestSide()
/// True if width be larger than 800
/// retorna True se a largura da tela for maior que 800px
context.showNavbar()
/// True if the shortestSide is smaller than 600p
/// retorna True se a menor dimensão (largura ou altura) da tela for menor que 600px
context.isPhone()
/// True if the shortestSide is largest than 600p
/// retorna True se a menor dimensão (largura ou altura) da tela for maior ou igual a 600px
context.isSmallTablet()
/// True if the shortestSide is largest than 720p
/// retorna True se a menor dimensão (largura ou altura) da tela for maior ou igual a 720px
context.isLargeTablet()
/// True if the current device is Tablet
/// retorna True se o dispositivo é um Tablet
context.isTablet()
/// Retorna um valor de acordo com o tamanho da tela
/// Os valores possíveis são:
/// swatch: se a menor dimensão (largura ou altura) da tela for menor que 300px
/// mobile: se a menor dimensão (largura ou altura) da tela for menor que 600px
/// tablet: se a menor dimensão (largura ou altura) da tela for menor que 1200px
/// desktop: se a largura da tela é maior ou iguial a 1200px
context.responsiveValue<T>()
```
### Configurações Globais opcionais e configurações manuais
... ... @@ -489,10 +567,45 @@ void localLogWriter(String text, {bool isError = false}) {
}
```
## Video explanation of Other GetX Features
### Widgets de Estado Local
Esses Widgets permitem que você gerencie um único valor e mantenha o estado efêmero e localmente. Temos versões para Reativo e Simples. Por exemplo, você pode usá-los para alternar obscureText em um TextField, talvez criar um painel expansível personalizado ou talvez modificar o índice atual em um BottomNavigationBar enquanto altera o conteúdo do corpo em um Scaffold.
#### ValueBuilder
Uma simplificação de StatefulWidget que funciona com um callback de "setState" que passa o valor atualizado.
```dart
ValueBuilder<bool>(
initialValue: false,
builder: (value, updateFn) => Switch(
value: value,
onChanged: updateFn, // mesma assinatura! Você poderia usar ( newValue ) => updateFn( newValue )
),
// se você precisa chamar algo fora do método builder.
onUpdate: (value) => print("Value updated: $value"),
onDispose: () => print("Widget unmounted"),
),
```
#### ObxValue
Similar a ValueBuilder, mas esta é a versão Reativa, você passa uma instância Rx (lembra do .obs mágico?) e
atualiza automaticamente... não é incrível?
```dart
ObxValue(
(data) => Switch(
value: data.value,
onChanged: data, // Rx tem uma função _callable_! Você poderia usar (flag) => data.value = flag,
),
false.obs,
),
```
## Explicação em vídeo sobre Outras Features do GetX
Amateur Coder did an awesome video about utils, storage, bindings and other features! Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
Amateur Coder fez um vídeo incrível sobre utils, storage, bindings e outras features! Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
# Breaking Changes da versão 2 para 3
... ... @@ -502,7 +615,7 @@ Amateur Coder did an awesome video about utils, storage, bindings and other feat
| -------- | ---------- |
| StringX | `RxString` |
| IntX | `RxInt` |
| MapX | `RxMax` |
| MapX | `RxMap` |
| ListX | `RxList` |
| NumX | `RxNum` |
| RxDouble | `RxDouble` |
... ... @@ -549,7 +662,7 @@ Agora:
```dart
GetMaterialApp(
getPages: [
GetPage(name: '/', page:()=> Home()),
GetPage(name: '/', page: () => Home()),
]
)
```
... ... @@ -558,7 +671,7 @@ GetMaterialApp(
Frequentemente, pode ser necessário decidir qual pagina vai ser mostrada ao usuário a partir de um parâmetro, como um token de login. A forma abordada anteriormente não era flexível, já que não permitia isso.
Inserir a página numa função reduziu significativamente o consumo de RAM, já que as rotas não são alocadas na memória desde o app inicia, e também permite fazer esse tipo de abordagem:
Inserir a página numa função reduziu significativamente o consumo de RAM, já que as rotas não são alocadas na memória no momento que o app é iniciado e também permite fazer esse tipo de abordagem:
```dart
... ... @@ -575,11 +688,11 @@ GetMaterialApp(
# Por que GetX?
1- Muitas vezes após uma atualização do Flutter, muitos dos seus packages irão quebrar. As vezes acontecem erros de compilação, muitas vezes aparecem erros que ainda não existem respostas sobre, e o desenvolvedor necessita saber de onde o erro veio, rastrear o erro, para só então tentar abrir uma issue no repositório correspondente, e ver seu problema resolvido. Get centraliza os principais recursos para o desenvolvimento (Gerencia de estado, de dependencias e de rotas), permitindo você adicionar um único package em seu pubspec, e começar a trabalhar. Após uma atualização do Flutter, a única coisa que você precisa fazer é atualizar a dependencia do Get, e começar a trabalhar. Get também resolve problemas de compatibilidade. Quantas vezes uma versão de um package não é compatível com a versão de outro, porque um utiliza uma dependencia em uma versão, e o outro em outra versão? Essa também não é uma preocupação usando Get, já que tudo está no mesmo package e é totalmente compatível.
1- Muitas vezes após uma atualização do Flutter, muitos dos seus packages irão quebrar. As vezes acontecem erros de compilação, muitas vezes aparecem erros que ainda não existem respostas sobre e o desenvolvedor necessita saber de onde o erro veio, rastreá-lo, para só então tentar abrir uma issue no repositório correspondente e ver seu problema resolvido. Get centraliza os principais recursos para o desenvolvimento (Gerência de estado, de dependências e de rotas), permitindo você adicionar um único package em seu pubspec e começar a trabalhar. Após uma atualização do Flutter, a única coisa que você precisa fazer é atualizar a dependencia do Get e começar a trabalhar. Get também resolve problemas de compatibilidade. Quantas vezes uma versão de um package não é compatível com a versão de outro, porque um utiliza uma dependência em uma versão e o outro em outra versão? Essa também não é uma preocupação usando Get, já que tudo está no mesmo package e é totalmente compatível.
2- Flutter é fácil, Flutter é incrível, mas Flutter ainda tem algum boilerplate que pode ser indesejado para maioria dos desenvolvedores, como o Navigator.of(context).push(context, builder[...]. Get simplifica o desenvolvimento. Em vez de escrever 8 linhas de código para apenas chamar uma rota, você pode simplesmente fazer: Get.to(Home()) e pronto, você irá para a próxima página. Urls dinamicas da web é algo realmente doloroso de fazer com o Flutter atualmente, e isso com o GetX é estupidamente simples. Gerenciar estados no Flutter, e gerenciar dependencias também é algo que gera muita discussão, por haver centenas de padrões na pub. Mas não há nada que seja tão fácil quanto adicionar um ".obs" no final de sua variável, e colocar o seu widget dentro de um Obx, e pronto, todas atualizações daquela variável será automaticamente atualizado na tela.
2- Flutter é fácil, Flutter é incrível, mas Flutter ainda tem algum boilerplate que pode ser indesejado para maioria dos desenvolvedores, como o Navigator.of(context).push(context, builder[...]. Get simplifica o desenvolvimento. Em vez de escrever 8 linhas de código para apenas chamar uma rota, você pode simplesmente fazer: Get.to(Home()) e pronto, você irá para a próxima página. Urls dinâmicas da web é algo realmente doloroso de fazer com o Flutter atualmente e isso com o GetX é estupidamente simples. Gerenciar estados no Flutter e gerenciar dependências também é algo que gera muita discussão, por haver centenas de padrões na pub. Mas não há nada que seja tão fácil quanto adicionar um ".obs" no final de sua variável, colocar o seu widget dentro de um Obx e pronto, todas atualizações daquela variável serão automaticamente atualizadas na tela.
3- Facilidade sem se preocupar com desempenho. O desempenho do Flutter já é incrível, mas imagine que você use um gerenciador de estados, e um locator para distribuir suas classes blocs/stores/controllers/ etc. Você deverá chamar manualmente a exclusão daquela dependencia quando não precisar dela. Mas já pensou em simplesmente usar seu controlador, e quando ele não tivesse mais sendo usado por ninguém, ele simplesmente fosse excluído da memória? É isso que GetX faz. Com o SmartManagement, tudo que não está sendo usado é excluído da memória, e você não deve se preocupar em nada além de programar. Você terá garantia que está consumindo o mínimo de recursos necessários, sem ao menos ter criado uma lógica para isso.
3- Facilidade sem se preocupar com desempenho. O desempenho do Flutter já é incrível, mas imagine que você use um gerenciador de estados e um locator para distribuir suas classes blocs/stores/controllers/ etc. Você deverá chamar manualmente a exclusão daquela dependência quando não precisar dela. Mas já pensou em simplesmente usar seu controlador e quando ele não tivesse mais sendo usado por ninguém, ele simplesmente fosse excluído da memória? É isso que GetX faz. Com o SmartManagement, tudo que não está sendo usado é excluído da memória e você não deve se preocupar em nada além de programar. Você terá garantia que está consumindo o mínimo de recursos necessários, sem ao menos ter criado uma lógica para isso.
4- Desacoplamento real. Você já deve ter ouvido o conceito "separar a view da lógica de negócios". Isso não é uma peculiaridade do BLoC, MVC, MVVM, e qualquer outro padrão existente no mercado tem esse conceito. No entanto, muitas vezes esse conceito pode ser mitigado no Flutter por conta do uso do context.
Se você precisa de context para localizar um InheritedWidget, você precisa disso na view, ou passar o context por parametro. Eu particularmente acho essa solução muito feia, e para trabalhar em equipes teremos sempre uma dependencia da lógica de negócios da View. Getx é pouco ortodoxo com a abordagem padrão, e apesar de não proibir totalmente o uso de StatefulWidgets, InitState, e etc, ele tem sempre uma abordagem similar que pode ser mais limpa. Os controllers tem ciclos de vida, e quando você precisa fazer uma solicitação APIREST por exemplo, você não depende de nada da view. Você pode usar onInit para iniciar a chamada http, e quando os dados chegarem, as variáveis serão preenchidas. Como GetX é totalmente reativo (de verdade, e trabalha sob streams), assim que os itens forem preenchidos, automaticamente será atualizado na view todos os widgets que usam aquela variável. Isso permite que as pessoas especialistas em UI trabalhem apenas com widgets, e não precisem enviar nada para a lógica de negócio além de eventos do usuário (como clicar em um botão), enquanto as pessoas que trabalham com a lógica de negócios ficarão livres para criar e testar a lógica de negócios separadamente.
4- Desacoplamento real. Você já deve ter ouvido o conceito "separar a view da lógica de negócios". Isso não é uma peculiaridade do BLoC, MVC ou MVVM, qualquer outro padrão existente no mercado tem esse conceito. No entanto, muitas vezes esse conceito pode ser mitigado no Flutter por conta do uso do context.
Se você precisa de context para localizar um InheritedWidget, você precisa disso na view ou passar o context por parâmetro. Eu particularmente acho essa solução muito feia e para trabalhar em equipes teremos sempre uma dependência da lógica de negócios da View. Getx é pouco ortodoxo com a abordagem padrão e apesar de não proibir totalmente o uso de StatefulWidgets, InitState e etc, ele tem sempre uma abordagem similar que pode ser mais limpa. Os controllers tem ciclos de vida e quando você precisa fazer uma solicitação APIREST por exemplo, você não depende de nada da view. Você pode usar onInit para iniciar a chamada http e quando os dados chegarem, as variáveis serão preenchidas. Como GetX é totalmente reativo (de verdade e trabalha sob streams), assim que os itens forem preenchidos, automaticamente será atualizado na view todos os widgets que usam aquela variável. Isso permite que as pessoas especialistas em UI trabalhem apenas com widgets e não precisem enviar nada para a lógica de negócio além de eventos do usuário (como clicar em um botão), enquanto as pessoas que trabalham com a lógica de negócio ficarão livres para criá-la e testá-la separadamente.
... ...
# Include option is buggy:
# https://github.com/flutter/flutter/issues/62591
# In case the include issue gets fixed, lines below INCLUDE_FIX
# can be removed
# include: package:effective_dart/analysis_options.1.2.0.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
await_only_futures: true
# This one is desirable, but that's a lot of work for now
public_member_api_docs: false
# Desirable, but would be breaking changes:
avoid_positional_boolean_parameters: false
constant_identifier_names: false
include_file_not_found: false
# INCLUDE_FIX (copy of effective dart 1.2.0)
# STYLE
camel_case_types: true
camel_case_extensions: true
library_names: true
file_names: true
library_prefixes: true
non_constant_identifier_names: true
directives_ordering: true
lines_longer_than_80_chars: true # avoid
curly_braces_in_flow_control_structures: true
# DOCUMENTATION
slash_for_doc_comments: true
package_api_docs: true # prefer
#- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
# USAGE
implementation_imports: true
avoid_relative_lib_imports: true # prefer
prefer_relative_imports: true # prefer
prefer_adjacent_string_concatenation: true
prefer_interpolation_to_compose_strings: true # prefer
unnecessary_brace_in_string_interps: true # avoid
prefer_collection_literals: true
avoid_function_literals_in_foreach_calls: true # avoid
prefer_iterable_whereType: true
prefer_function_declarations_over_variables: true
unnecessary_lambdas: true
prefer_equal_for_default_values: true
avoid_init_to_null: true
unnecessary_getters_setters: true
#- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
#- prefer_expression_function_bodies # consider
unnecessary_this: true
prefer_initializing_formals: true
type_init_formals: true
empty_constructor_bodies: true
unnecessary_new: true
unnecessary_const: true
avoid_catches_without_on_clauses: true # avoid
avoid_catching_errors: true
use_rethrow_when_possible: true
# DESIGN
use_to_and_as_if_applicable: true # prefer
one_member_abstracts: true # avoid
avoid_classes_with_only_static_members: true # avoid
prefer_mixin: true
prefer_final_fields: true # prefer
use_setters_to_change_properties: true
avoid_setters_without_getters: true
avoid_returning_null: true # avoid
avoid_returning_this: true # avoid
type_annotate_public_apis: true # prefer
#- prefer_typing_uninitialized_variables # consider
omit_local_variable_types: true # avoid
avoid_types_on_closure_parameters: true # avoid
avoid_return_types_on_setters: true # avoid
prefer_generic_function_type_aliases: true
avoid_private_typedef_functions: true # prefer
#- use_function_type_syntax_for_parameters # consider
hash_and_equals: true
avoid_equals_and_hash_code_on_mutable_classes: true # avoid
avoid_null_checks_in_equality_operators: true
... ...
# benchmarks
A repository to benchmark Flutter libs.
Creators of the tested libs can suggest improvements, as long as they follow the same design structure.
# 1- State Managers
![](benchmark.png)
The idle application consumes 4.288k of ram.
Items were added dynamically to a ListView.
The amount of RAM was measured after the test, and the following calculation was made:
Number of RAM consumed by the app after testing with the state manager - RAM in idle state without any state manager.
In addition to the RAM calculation, the size of the apk was also observed after compilation. And we had the following results:
- flutter_bloc: 8.3mb
- mobx: 8.3mb
- provider: 8.3mb
- redux: 8.2mb
- get: 8.2mb
- getx: 8.2mb
The creators of flutter_bloc and provider made changes to use their library. If you want to make changes (within the scope of the project, without eliminating classes), you can do so by offering a PR.
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 29
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "de.udos.flutterstatemanagement"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.udos.benchmarks">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.udos.benchmarks">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="benckmark"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
package de.udos.benchmarks;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
package io.flutter.plugins;
import io.flutter.plugin.common.PluginRegistry;
/**
* Generated file. Do not edit.
*/
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
}
package de.udos.benchmarks
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
package de.udos.benchs
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.udos.benchmarks">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
#Sat Jan 11 20:55:27 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
sdk.dir=/home/jonny/Android/Sdk
flutter.sdk=/opt/flutter
flutter.buildMode=profile
\ No newline at end of file
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/opt/flutter
FLUTTER_APPLICATION_PATH=/home/jonny/Área de trabalho/getx/benchmark/state_managers
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
SYMROOT=${SOURCE_ROOT}/../build/ios
OTHER_LDFLAGS=$(inherited) -framework Flutter
FLUTTER_FRAMEWORK_DIR=/opt/flutter/bin/cache/artifacts/engine/ios
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=false
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.packages
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/opt/flutter"
export "FLUTTER_APPLICATION_PATH=/home/jonny/Área de trabalho/getx/benchmark/state_managers"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
export "FLUTTER_FRAMEWORK_DIR=/opt/flutter/bin/cache/artifacts/engine/ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
//
// Generated file. Do not edit.
//
#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end
NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */
//
// Generated file. Do not edit.
//
#import "GeneratedPluginRegistrant.h"
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>benckmark</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:benckmark/item.dart';
part 'items_event.dart';
class ItemsBloc extends Bloc<ItemsEvent, List<Item>> {
ItemsBloc() {
Timer.periodic(const Duration(milliseconds: 500), (timer) {
add(AddItemEvent(Item(title: DateTime.now().toString())));
if (state.length == 10) {
timer.cancel();
print("It's done. Print now!");
}
});
}
@override
List<Item> get initialState => sampleItems;
@override
Stream<List<Item>> mapEventToState(ItemsEvent event) async* {
if (event is AddItemEvent) {
yield List.from(state)..add(event.item);
}
}
}
part of 'items_bloc.dart';
abstract class ItemsEvent {}
class AddItemEvent extends ItemsEvent {
AddItemEvent(this.item);
final Item item;
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:benckmark/item.dart';
import 'package:benckmark/_bloc_lib/_blocs/items/items_bloc.dart';
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'BLoC Lib Sample',
theme: ThemeData(primarySwatch: Colors.blue),
home: BlocProvider(
create: (_) => ItemsBloc(),
child: Page(title: 'BLoC Lib Sample'),
),
);
}
}
class Page extends StatelessWidget {
const Page({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: BlocBuilder<ItemsBloc, List<Item>>(
builder: (context, items) {
return ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(items[index].title));
},
);
},
),
);
}
}
import 'dart:async';
import 'package:benckmark/item.dart';
import 'package:rxdart/rxdart.dart';
class AddItemEvent {
final Item item;
AddItemEvent(this.item);
}
class ItemsBloc {
final StreamController<dynamic> _itemsEventController = StreamController();
StreamSink<dynamic> get _itemsEventSink => _itemsEventController.sink;
final BehaviorSubject<List<Item>> _itemsStateSubject =
BehaviorSubject.seeded(sampleItems);
StreamSink<List<Item>> get _itemsStateSink => _itemsStateSubject.sink;
ValueStream<List<Item>> get items => _itemsStateSubject.stream;
List<StreamSubscription<dynamic>> _subscriptions;
ItemsBloc() {
_subscriptions = <StreamSubscription<dynamic>>[
_itemsEventController.stream.listen(_mapEventToState)
];
}
dispose() {
_subscriptions.forEach((subscription) => subscription.cancel());
_itemsStateSubject.close();
_itemsEventController.close();
}
void addItem(Item item) {
_itemsEventSink.add(AddItemEvent(item));
}
void _mapEventToState(dynamic event) {
if (event is AddItemEvent) {
_itemsStateSink.add([...items.value, event.item]);
}
}
}
import 'package:flutter/widgets.dart';
import '_bloc.dart';
class ItemsBlocProvider extends InheritedWidget {
final ItemsBloc bloc;
ItemsBlocProvider({
Key key,
Widget child,
@required this.bloc,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) => true;
static ItemsBloc of(BuildContext context) {
final provider =
context.dependOnInheritedWidgetOfExactType<ItemsBlocProvider>();
return provider.bloc;
}
}
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:benckmark/item.dart';
import '_bloc.dart';
import '_provider.dart';
class App extends StatelessWidget {
final ItemsBloc itemsBloc = ItemsBloc();
@override
Widget build(BuildContext context) {
return ItemsBlocProvider(
bloc: itemsBloc,
child: MaterialApp(
title: 'BLoC Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page(title: 'BLoC Sample'),
),
);
}
}
class Page extends StatefulWidget {
Page({Key key, this.title}) : super(key: key);
final String title;
@override
_PageState createState() => _PageState();
}
class _PageState extends State<Page> {
@override
void initState() {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) async {
for (int i = 0; i < 10; i++) {
await Future.delayed(Duration(milliseconds: 500));
ItemsBlocProvider.of(context)
.addItem(Item(title: DateTime.now().toString()));
}
print("It's done. Print now!");
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListViewWidget(),
);
}
}
class ListViewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final ItemsBloc itemsBloc = ItemsBlocProvider.of(context);
return StreamBuilder<List<Item>>(
stream: itemsBloc.items,
builder: (context, snapshot) {
final items = snapshot.data;
return ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: items is List<Item> ? items.length : 0,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index].title),
);
},
);
},
);
}
}
import 'package:benckmark/item.dart';
import 'package:get/get.dart';
class Controller extends GetController {
@override
onInit() async {
for (int i = 0; i < 10; i++) {
await Future.delayed(Duration(milliseconds: 500));
addItem(Item(title: DateTime.now().toString()));
}
print("It's done. Print now!");
super.onInit();
}
final items = List<Item>.of(sampleItems);
void addItem(Item item) {
items.add(item);
update();
}
}
import 'package:flutter/material.dart';
import 'package:benckmark/_get/_store.dart';
import 'package:get/get.dart';
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Get Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page(title: 'Get Sample'),
);
}
}
class Page extends StatelessWidget {
Page({
Key key,
this.title,
}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListViewWidget(),
);
}
}
class ListViewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetBuilder<Controller>(
init: Controller(),
global: false,
builder: (_) => ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: _.items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_.items[index].title),
);
}));
}
}
import 'package:benckmark/item.dart';
import 'package:get/get.dart';
class Controller extends RxController {
Controller() {
onInit();
}
final items = sampleItems.obs;
@override
onInit() async {
for (int i = 0; i < 10; i++) {
await Future.delayed(Duration(milliseconds: 500));
addItem(Item(title: DateTime.now().toString()));
}
print("It's done. Print now!");
super.onInit();
}
void addItem(Item item) {
items.add(item);
}
}
import 'package:benckmark/_get_rx/_store.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GetX Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page(title: 'GetX Sample'),
);
}
}
class Page extends StatelessWidget {
Page({
Key key,
this.title,
}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("GetX"),
),
body: ListViewWidget(),
);
}
}
class ListViewWidget extends StatelessWidget {
final Controller c = Controller();
@override
Widget build(BuildContext context) {
return Obxx(() => ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: c.items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(c.items[index].title),
);
}));
}
}
import 'package:benckmark/item.dart';
import 'package:mobx/mobx.dart';
part '_store.g.dart';
class AppStore = _AppStore with _$AppStore;
abstract class _AppStore with Store {
@observable
ObservableList<Item> items = ObservableList<Item>.of(sampleItems);
@observable
ObservableSet<String> checkedItemIds = ObservableSet<String>();
@action
void addItem(Item item) {
items.add(item);
}
}
// GENERATED CODE - DO NOT MODIFY BY HAND
part of '_store.dart';
// **************************************************************************
// StoreGenerator
// **************************************************************************
// ignore_for_file: non_constant_identifier_names, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
mixin _$AppStore on _AppStore, Store {
final _$itemsAtom = Atom(name: '_AppStore.items');
@override
ObservableList<Item> get items {
_$itemsAtom.context.enforceReadPolicy(_$itemsAtom);
_$itemsAtom.reportObserved();
return super.items;
}
@override
set items(ObservableList<Item> value) {
_$itemsAtom.context.conditionallyRunInAction(() {
super.items = value;
_$itemsAtom.reportChanged();
}, _$itemsAtom, name: '${_$itemsAtom.name}_set');
}
final _$checkedItemIdsAtom = Atom(name: '_AppStore.checkedItemIds');
@override
ObservableSet<String> get checkedItemIds {
_$checkedItemIdsAtom.context.enforceReadPolicy(_$checkedItemIdsAtom);
_$checkedItemIdsAtom.reportObserved();
return super.checkedItemIds;
}
@override
set checkedItemIds(ObservableSet<String> value) {
_$checkedItemIdsAtom.context.conditionallyRunInAction(() {
super.checkedItemIds = value;
_$checkedItemIdsAtom.reportChanged();
}, _$checkedItemIdsAtom, name: '${_$checkedItemIdsAtom.name}_set');
}
final _$_AppStoreActionController = ActionController(name: '_AppStore');
@override
void addItem(Item item) {
final _$actionInfo = _$_AppStoreActionController.startAction();
try {
return super.addItem(item);
} finally {
_$_AppStoreActionController.endAction(_$actionInfo);
}
}
}
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:benckmark/_mobx/_store.dart';
import 'package:benckmark/item.dart';
final store = AppStore();
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MobX Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page(title: 'MobX Sample'),
);
}
}
class Page extends StatefulWidget {
Page({
Key key,
this.title,
}) : super(key: key);
final String title;
@override
_PageState createState() => _PageState();
}
class _PageState extends State<Page> {
@override
void initState() {
fill();
super.initState();
}
fill() async {
for (int i = 0; i < 10; i++) {
await Future.delayed(Duration(milliseconds: 500));
store.addItem(Item(title: DateTime.now().toString()));
}
print("It's done. Print now!");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListViewWidget(),
);
}
}
class ListViewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Observer(
builder: (_) {
return ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: store.items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(store.items[index].title),
);
},
);
},
);
}
}
import 'package:flutter/foundation.dart';
import 'package:benckmark/item.dart';
import 'package:flutter/scheduler.dart';
class AppState with ChangeNotifier {
AppState() {
SchedulerBinding.instance.addPostFrameCallback((timeStamp) async {
for (int i = 0; i < 10; i++) {
await Future.delayed(Duration(milliseconds: 500));
addItem(Item(title: DateTime.now().toString()));
}
print("It's done. Print now!");
});
}
List<Item> _items = sampleItems;
List<Item> get items => _items;
void addItem(Item item) {
_items.add(item);
notifyListeners();
}
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '_state.dart';
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => AppState(),
child: MaterialApp(
title: 'Provider Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page(title: 'Provider Sample'),
),
);
}
}
class Page extends StatelessWidget {
Page({
Key key,
this.title,
}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListViewWidget(),
);
}
}
class ListViewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final state = context.watch<AppState>();
return ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: state.items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(state.items[index].title),
);
},
);
}
}
import 'package:benckmark/item.dart';
import 'package:meta/meta.dart';
@immutable
class AppState {
final List<Item> items;
AppState({
this.items,
});
AppState.initialState() : items = sampleItems;
}
class AddItemAction {
Item payload;
AddItemAction({
this.payload,
});
}
AppState appReducer(AppState state, dynamic action) {
return AppState(items: itemsReducer(state.items, action));
}
List<Item> itemsReducer(List<Item> state, dynamic action) {
if (action is AddItemAction) {
return [...state, action.payload];
}
return state;
}
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:benckmark/item.dart';
import 'package:redux/redux.dart';
import '_store.dart';
final store =
Store<AppState>(appReducer, initialState: AppState.initialState());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StoreProvider<AppState>(
store: store,
child: MaterialApp(
title: 'Redux Sample',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page(title: 'Redux Sample'),
),
);
}
}
class Page extends StatefulWidget {
Page({
Key key,
this.title,
}) : super(key: key);
final String title;
@override
_PageState createState() => _PageState();
}
class _PageState extends State<Page> {
@override
void initState() {
super.initState();
fill();
}
fill() async {
for (int i = 0; i < 10; i++) {
await Future.delayed(Duration(milliseconds: 500));
store.dispatch(
AddItemAction(payload: Item(title: DateTime.now().toString())));
}
print("It's done. Print now!");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListViewWidget(),
);
}
}
class ListViewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, List<Item>>(
converter: (store) => store.state.items,
builder: (context, items) {
return ListView.builder(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index].title),
);
},
);
},
);
}
}
class Item {
final String title;
Item({
this.title,
});
}
final List<Item> sampleItems = [
Item(title: 'Item 1'),
Item(title: 'Item 2'),
Item(title: 'Item 3')
];
import 'package:flutter/widgets.dart';
//import 'package:benckmark/_bloc_plain/app.dart';
//import 'package:benckmark/_bloc_lib/app.dart';
//import 'package:benckmark/_mobx/app.dart';
//import 'package:benckmark/_redux/app.dart';
//import 'package:benckmark/_get_rx/app.dart';
//import 'package:benckmark/_provider/app.dart';
import 'package:benckmark/_get/app.dart';
void main() => runApp(App());
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.39.10"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.2"
bloc:
dependency: "direct main"
description:
name: bloc
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
build:
dependency: transitive
description:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.9"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "5.2.0"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "4.3.2"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "7.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "3.3.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0-nullsafety"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.1"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.6"
equatable:
dependency: "direct main"
description:
name: equatable
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.11"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
flutter_mobx:
dependency: "direct main"
description:
name: flutter_mobx
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.7"
flutter_redux:
dependency: "direct main"
description:
name: flutter_redux
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
get:
dependency: "direct main"
description:
name: get
url: "https://pub.dartlang.org"
source: hosted
version: "2.12.5-beta"
glob:
dependency: transitive
description:
name: glob
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
html:
dependency: transitive
description:
name: html
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.0+3"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
io:
dependency: transitive
description:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.4"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.2"
json_annotation:
dependency: transitive
description:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.4"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.8"
meta:
dependency: "direct main"
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.6+3"
mobx:
dependency: "direct main"
description:
name: mobx
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0+4"
mobx_codegen:
dependency: "direct dev"
description:
name: mobx_codegen
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4"
node_interop:
dependency: transitive
description:
name: node_interop
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
pool:
dependency: transitive
description:
name: pool
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.0"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.3"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.4"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
redux:
dependency: "direct main"
description:
name: redux
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
rxdart:
dependency: "direct main"
description:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.23.1"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.5"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.3"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.5"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.5"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
stream_transform:
dependency: transitive
description:
name: stream_transform
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.17"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1+2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety"
uuid:
dependency: "direct main"
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0-nullsafety"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.7+15"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
sdks:
dart: ">=2.9.0-18.0 <2.9.0"
flutter: ">=1.16.0"
name: benckmark
description: A new Flutter application showing different kinds of state management.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
get: 2.12.5-beta
bloc: ^4.0.0
equatable: ^1.0.2
flutter_bloc: ^4.0.0
flutter_mobx: ^0.3.6
flutter_redux: ^0.6.0
meta:
mobx: ^0.4.0+1
provider: ^4.0.1
redux: ^4.0.0
rxdart: ^0.23.1
uuid: ^2.0.4
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.7.3
mobx_codegen: ^0.4.0+1
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.io/custom-fonts/#from-packages
\ No newline at end of file