Nipodemos

Merge branch 'master'

Conflicts:
	benchmark/state_managers/pubspec.lock
	example/pubspec.lock
	lib/src/context_extensions/extensions.dart
	lib/src/extensions/context_extensions.dart
	lib/src/extensions/string_extensions.dart
	lib/src/regex/get_utils_extensions.dart
	lib/src/utils/context_extensions/extensions.dart
	lib/src/utils/regex/get_utils_extensions.dart
	lib/utils.dart
	pubspec.lock
Showing 75 changed files with 1969 additions and 1511 deletions

Too many changes to show.

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

{
"cSpell.enableFiletypes": [
"markdown"
]
}
\ No newline at end of file
... ...
## [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
## [3.4.5]
- Fix typo on RxList.remove that could cause type errors.
- Remove initialization console print
## [3.4.4]
- 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
- Fix language callback(@lundin)
- Fix docs (@nipodemos)
## [3.4.2]
- Fix individual imports
## [3.4.1]
- Structure organization, and improvements.
## [3.4.0]
- Added '[everAll]' Worker: Listen a List of '.obx'
- Added Workers dispose
- Fix transition.noTransition
- Fix TextField and VideoPlayController dispose before transition animation
## [3.3.0]
- Fix extensions (@stefandevo)
- Added CPF to utils options (@kauemurakami)
... ...
![](get.png)
*Idiomas: Español (este archivo), [Inglés](README.md), [Portugués de Brasil](README.pt-br.md).*
*Idiomas: Español (este archivo), [Inglés](README.md), [Portugués de Brasil](README.pt-br.md), [Polaco](README.pl.md).*
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
... ... @@ -106,7 +106,7 @@ void main() => runApp(GetMaterialApp(home: Home()));
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 {
class Controller extends GetxController {
var count = 0.obs;
increment() => count.value++;
}
... ... @@ -141,6 +141,7 @@ class Other extends StatelessWidget {
Widget build(context){
// Access the updated count variable
return Scaffold(body: Center(child: Text(c.count.string)));
}
}
```
... ...
![](get.png)
*Languages: English (this file), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md).*
*Languages: English (this file), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md),[Polish](README.pl.md).*
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![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)
[![Discord Shield](https://discordapp.com/api/guilds/722900883784073290/widget.png?style=shield)](https://discord.com/invite/9Hpt99N)
<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>
... ... @@ -40,20 +40,27 @@
[**Slack (English)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Discord (English and Portuguese)**](https://discord.com/invite/9Hpt99N)
[**Discord (English, Spanish 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 is not for everyone, its focus is (performance) on the minimum consumption of resources ([look the benchmarks](https://github.com/jonataslaw/benchmarks)), (productivity) using an easy and pleasant syntax and (organization) allowing the total decoupling of the View from the business logic.
- 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 is not `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 AOT which is incredible, and manages to eliminate unused resources like no other framework does.
**GetX makes your development productive, but want to make it even more productive? Add the extension [GetX extension](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) to your VSCode**. Not available in other IDEs for now.
- 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.
- 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 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 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**
# Installing
... ... @@ -205,10 +212,9 @@ GetMaterialApp( // Before: MaterialApp(
home: MyHome(),
)
```
To navigate to a new screen:
Navigate to new screen:
```dart
Get.to(NextScreen());
```
... ... @@ -253,6 +259,7 @@ Controller controller = Get.put(Controller()); // Rather Controller controller =
Instead of instantiating your class within the class you are using, you are instantiating it within the Get instance, which will make it available throughout your App.
So you can use your controller (or class Bloc) normally
**Tip:** Get dependency management is decloupled from other parts of the package, so if for example your app is already using a state manager (any one, it doesn't matter), you don't need to rewrite it all, you can use this dependency injection with no problems at all
```dart
... ... @@ -424,6 +431,14 @@ context.isLargeTablet()
/// True if the current device is Tablet
context.isTablet()
/// Returns a value according to the screen size
/// can give value for
/// swatch: 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
... ... @@ -467,6 +482,22 @@ 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.
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// pass the message to your favourite logging package here
// please note that even if enableLog: false log messages will be pushed in this callback
// you get check the flag if you want through GetConfig.isLogEnable
}
```
## Video explanation of Other GetX Features
... ... @@ -481,7 +512,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` |
| DoubleX | `RxDouble` |
... ...
![](get.png)
*Languages: [English](README.md), [Brazilian Portuguese](README.pt-br.md), [Spanish](README-es.md), Polish (Jesteś tu).*
[![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)
<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)
- [Wprowadzenie](#wprowadzenie)
- [Instalacja](#instalacja)
- [Counter App z GetX](#counter-app-z-getx)
- [Trzy fialary](#trzy-filary)
- [Menadżer stanu](#menadżer-stanu)
- [Reaktywny menadżer stanu](#reaktywny-menadżer-stanu)
- [Bardziej szczegółowo o menadżerze stanu](#bardziej-szczegółowo-o-menadżerze-stanu)
- [Video tłumaczące użycie menadżera stanu](#video-tłumaczące-użycie-menadżera-stanu)
- [Zarzadzanie routami](#zarządzanie-routami)
- [Więcej o routach](#więcej-o-routach)
- [Video tłumaczące użycie](#video-tłumaczące-użycie)
- [Zarządzanie dependencies](#zarządzanie-dependencies)
- [Bardziej szczefółowo o menadżerze dependencies](#bardziej-szczegółowo-o-menadżerze-dependencies)
- [Jak włożyć coś od siebie](#jak-włożyć-coś-od-siebie)
- [Narzędzia](#narzędzia)
- [Zmiana motywu](#zmiana-motywu)
- [Inne zaawansowane API](#inne-zaawansowane-api)
- [Opcjonalne globalne ustawienia i manualna konfiguracja](#opcjonalne-globalne-ustawienia-i-manualna-konfiguracja)
- [Video tłumaczace inne funkcjonalności GetX](#video-tłumaczące-inne-funkcjonalności-getx)
- [Zmiany od 2.0](#zmiany-od-20)
# Kanały komunikacji i wsparcia:
[**Slack (English)**](https://communityinviter.com/apps/getxworkspace/getx)
[**Discord (English and Portuguese)**](https://discord.com/invite/9Hpt99N)
[**Telegram (Portuguese)**](https://t.me/joinchat/PhdbJRmsZNpAqSLJL6bH7g)
# Wprowadzenie
- GetX jest bardzo lekką i potężną biblioteką do Flattera. Łączy wysoką wydajność menadżera stanu, inteligętne dodawanie dependencies i zarządzanie routami w szybki i praktyczny sposób.
- GetX nie jest dla wszystkich, skupia się na jak najmniejszej konsumpcji zasobów (wydajności) ([zobacz benchmarki](https://github.com/jonataslaw/benchmarks)), używaniu łatwej skłani (produktywności) i daniu możliwości pełnego rozbicia View na z logiki biznesowej (organizacja).
- GetX która da Ci supermoce i zwiększy produktywność w tworzeniu projektu. Oszczędzi godziny zarówno początkującym jak i ekspoertom.
- Nawiguj bez podawania `context`, używaj open `dialogs`, `snackbarów` oraz `bottomsheetów` z każdego miejsca w kodzie. Zarządzaj stanami i dodawaj dependencies w prosty i praktyczny sposób!
- Get jest bezpieczny, stabilny i aktualny. Oprócz tego oferuje szeroki zakres API, które nie są zawarte w standardowym frameworku.
- GetX nie jest przytłaczający. Ma wiele funkcjonalności pozwalajacych na rozpoczęcie programowania bez martwienia się o nic, ale wszystkie te funkcjonalności są w osobnych kontenerach będących dodane dopiero po ich użyciu. Jeśli tylko używasz menadżera stanu, tylko on będzie kompilowany. Jeśli używasz routów, lecz nic z menadżera stanu on nie będzie kompilowany. Możesz skompilować repozytorium benchmark i zobaczysz że używa tylko menadżera stanu. Aplikacje używajace Get są mniejsze niz inne ponieważ wszystkie rozwiązania GetX sa projektowane dla lekkości i wydajności. Jest to też zasługa Flutterowego AOT, które jest niesamowite i eliminuje nieużywane zasoby jak żaden inny framework.
**GetX zwiększa stwoja produktywność, lecz mozesz to jeszcze przyspieszyć instalując rozszerzenie [GetX extension](https://marketplace.visualstudio.com/items?itemName=get-snippets.get-snippets) do swojego VSCode**. Jeszcze nie dostępne w innych IDE.
# Instalacja
Dodaj Get do swojego pliku pubspec.yaml:
```yaml
dependencies:
get:
```
Zaimportuj Get do plików w których chcesz go użyć:
```dart
import 'package:get/get.dart';
```
# Counter App z GetX
Przykładowa aplikaja tworzona domyślnie podczas kreacji nowego projektu we Flaterze ma ponad 100 lini kodu (z komentarzami). By pokazać siłę Get pokarzę jak zrobić "licznik" ze zmienianą stan z każdym kliknięciem, zmianą stron i udostępniajac stan pomiędzy ekranami. Wszystko w zorganizowany sposób dzieląc buissnes logic z view w zaledwie 26 LINI KODU WŁĄCZAJĄC W TO KOMENTARZE.
-Krok 1:
Dodaj "Get" przed MaterialApp, zamieniając je na GetMaterialApp
```dart
void main() => runApp(GetMaterialApp(home: Home()));
```
- Note: nie jest to modyfikaja MaterialApp, ponieważ GetMaterialApp nie jest zmodyfikowanym MaterialApp z Fluttera, jest tylko zkonfigurowanym Widgetem mającym domyślnie MaterialApp jako dziecko. Możesz to konfigurować ręcznie, ale nie jest to konieczne. GetMaterialApp jest niezbędne dla działania routów, snackbarów, bootomsheetów, internacjonalizacji, dialogów i wysokopoziomowych api powiązanych z routami i nieobecnościa kontekstu. Nie jest to jednak wymagane do używania zarzadzania stanem i dependencies.
-Krok 2:
Tworzymy klasę business logic i umieszczmy w niej wszystkie zmienne, metody oraz kontrolery. Możesz zmienić zmienna=ą na obserwowalną używajac prostego ".obs"
```dart
class Controller extends GetxController{
var count = 0.obs;
increment() => count.value++;
}
```
- Krok 3:
Tworzymy View. Użyj StatelessWidget oszczędzajac przy tym RAM. Z Get nie będzie Ci potrzebny StatefullWidget.
```dart
class Home extends StatelessWidget {
// Instantiate your class using Get.put() to make it available for all "child" routes there.
final Controller c = Get.put(Controller());
@override
Widget build(context) => Scaffold(
// Use Obx(()=> to update Text() whenever count is changed.
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
body: Center(child: RaisedButton(
child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
}
class Other extends StatelessWidget {
// You can ask Get to find a Controller that is being used by another page and redirect you to it.
final Controller c = Get.find();
@override
Widget build(context){
// Access the updated count variable
return Scaffold(body: Center(child: Text(c.count.string)));
}
}
```
Wynik:
![](counter-app-gif.gif)
Jest to prosty projekt, ale już na jego przykładzie widać potęgę Get. Wzraz ze wzrostem rozmiaru aplikacji ta różnica tylko się powieksza.
Get był projektowany dla pracy z zespołem, ale równie dobrze sprawdza się w indywidualnej pracy.
Zawsze dotrzymuj deadlinów i dostarczaj swoje rozwiązania na czas bez straty na wydajności. Get nie jest dla wszystkich jak już wspominałem, ale jeśli identyfikujesz się z powyższym zdaniem Get jest dla ciebie.
# Trzy filary
## Menadżer stanu
Obecnie istnieje kilka menadżeów dla Fluttera. Jednak większość z nich wymaga używania ChangeNotifier, po to aby zaktualizować widżety, co nie sprawdza się pod kątem wydajności w średnich i dużych aplikacach. Możesz sprawdzić w oficjalnej dokumentacji, że ChangeNotifier powinien być używany z maksimum dwoma listinerami (https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html), będąc praktycznie bezużytecznym w średnich i duzych projektach.
Get nie jest ani lepszy, ani gorszy od innych menadżerów stanów, ale powinieneś rozpatrzyć te punkty jak i poniższe, aby wybrać między użyciem Get w czystej formie (Vanilla), albo używaniem go wraz z innym menadżerem.
Definitywnie Get nie jest przeciwnikiem żadnego innego menadżera, ponieważ jest on mikroframeworkiem, nie tylko menadżerem stanu. Może być użyty samodzielnie, lub w koegzystencji.
Get ma bardzo lekki i prosty menadżer stanu (napisany w tylko 95 lini kodu), który nie używa ChangeNotifier. Sprosta on wymaganiom szczególnie nowych we Flutterze i nie sprawi problemu nawer w dużych aplikacjach.
### Reaktywny menadżer stanu
Reaktywne programowanie możee dotrącać niektórych, ponieważ powszechnie jest uważane za skomplikowane. GetX zamienia to w coś prostego:
- Nie musisz tworzyć Strw=eamControllerów,
- Nie musisz tworzyć StreamBuildera dla każdej zmiennej,
- Nie ma potrzeby tworzenia klasy dla kżdego stanu,
- Nie musisz tworzyć Get dla inicjalnej zmiennej
Wyobraź sobie, że masz zmienną i za każdym razem jak zmienisz ją chcesz żeby wszystkie widżety używające jej automatycznie się zmieniły
Przykładowa zmienna:
```dart
var name = 'Jonatas Borges';
```
By zamienić ją na obserwowalną dodaj ".obx" na końcu:
```dart
var name = 'Jonatas Borges'.obs;
```
I w UI, kiedy chcesz go zaktualizować przy modyfikacji zmiennej po prostu dodaj to:
```dart
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**
### Video tłumaczące użycie menadżera stanu
Amateur COder nagrał o tym niezwykły film:
Link: [Complete GetX State Management](https://www.youtube.com/watch?v=CNpXbeI_slw)
## Zarządzanie routami
Jeśli chcesz używać routes/snackbars/dialogs/bottomsheets z GetX możesz to robić bez contextu.
Zamień MaterialApp na GetMaterialApp
```dart
GetMaterialApp( // Before: MaterialApp(
home: MyHome(),
)
```
By nawigować do nowego ekranu:
```dart
Get.to(NextScreen());
```
By powrócić do poprzedniego ekranu
```dart
Get.back();
```
By przejść do następnego ekranu bez możliwości powrotu do poprzedniego (do zastosowania SplashScreenów, ekranów logowania itd.)
```dart
Get.off(NextScreen());
```
By przejść do następnego ekranu niszcząc poprzednie routy (użyteczne w koszykach, ankietach i testach)
```dart
Get.offAll(NextScreen());
```
By nawigować do następnego routa i otrzymać, lub uaktualnić dane zaraz po tym jak z niego wrócisz:
```dart
var data = await Get.to(Payment());
```
w innym ekranie wyślij dane z poprzedniego routa:featury
```dart
Get.back(result: 'sucess');
```
I użyj następujące np.:
```dart
if(data == 'sucess') madeAnything();
```
Zobacz, ze do żadnej z tych operacji nie potrzebowałeś contextu. Jest to jedna z głównych zalet GetX oszczędzającego na niepotrzebnej ogudowie z kod i dającego możliwość uzywania tych metod w klasie kontrolera.
### 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)**
### Video tłumaczące użycie
Amateur Coder nagrał o tym niezwykły film:
Link: [Complete GetX Navigation](https://www.youtube.com/watch?v=RaqPIoJSTtI)
## Zarządzanie dependencies
Get ma prosty i potężny menadżer dependencies. Pozwala on na otrzymanie tych samych klas jak twoje Bloc lub Kontroler piszac jedną linię kodu bez Provider context i inheritedWidget:
```dart
Controller controller = Get.put(Controller()); // Rather Controller controller = Controller();
```
- Note: Jeśli używasz menadżera stanu Get zwróć uwafę na binding api, które pozwoli Ci łatwiej połączyć twój widok z kontrolerem.
https://github.com/jonataslaw/get
**Tip:** Menadżer dependency Get jest oddzielony od innych części pakietu więc jeśli już używasz menadzera stanu(którego kolwiek,bez różnicy) nie musisz przepisywać tego wszystkiego na nowo. Możesz używać tego dodawania dependencies bez poroblemu.
```dart
controller.fetchApi();
```
Wyobraź sobie, że musisz nawigować pomiędzy wieloma routami i potrzebujesz dane z kontrolerów z poprzednich ekranów. Musiałbyś użyć menadżera stanu z dodatkiem Providera albo Get_it, prawda? Otuż nie z Fet. Muszisz po prostu poprosić Get o znalezienie tego kontrolera i nie potrzebujesz przy tym dodatkowych dependencies.
```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 controllersfeatury instantiated, Get will always give you the right controller.
```
I wtedy będziesz mógł otrzymać bez problemu z niego dane
```dart
Text(controller.textFromApi);
```
### Bardziej szczegółowo o menadżerze dependencies
**Zobzcz więcej w dokumentacji [tutaj](./docs/en_US/dependency_management.md)**
# Jak włożyć coś od siebie
Możesz uczestniczyć w rozwoju projektu na różny sposób:
- Pomagając w tłumaczeniu readme na inne języki.
- Dodając dokumentację do readme ( nawet nie połowa funkcji została jeszcze opisana).
- Pisząc artykuły i nagrywając filmy uczące użycia biblioteki Get (będą zamieszczone w readme, a w przyszłości na naszej Wiki).
- Oferując PR-y dla kodu i testów.
- Dodając nowe funkcje.
Każda współpraca jest mile widziana!
# Narzędzia
## Zmiana motywu
Nie powinno się uzywać innego widżetu niż GetMaterialApp by go zaktualizować. To może powodować duplikacje kluczy. Wiele osób nawykło do prehistorycznego podejścia tworzenia widżetu "ThemeProvider" tylko po to by zmienić motyw aplikacji. Z Get nie jest to absolutnie wymagane.
Możesz stworzyć customowy motyw i łatwo go dodać z Get.changeTheme bez niepotrzebnego kodu.
```dart
Get.changeTheme(ThemeData.light());
```
Jeśli chcesz stworzyć coś jak przycisk zmieniający motyw aplikacji na onTap, możesz połączyć dwia Get API. Api sprawdzające czy ciemny motyw jest używany i Api zajmujące się zmianą motywu. Po prostu użyj tego w onPressed:
```dart
Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());featury
```
Kiedy ciemny motyw jest aktywny zmieni się on na jasny, w przeciwnym wypadku zmieni się na ciemny.
Jeśli interesuje Cię jak zmieniać motywy podąrzaj za samouczkiem na Medium uczącym zmiany motywu z Get:
- [Dynamic Themes in 3 lines using Get](https://medium.com/swlh/flutter-dynamic-themes-in-3-lines-c3b375f292e3) - Samouczek stworzony przez [Rod Brown](https://github.com/RodBr).
## Inne zaawansowane API
```dart
// give the current args from currentScreen
Get.arguments
// give arguments of previous route
Get.previousArguments
// give name of previous route
Get.previousRoute
// give the raw route to access for example, rawRoute.isFirst()
Get.rawRoute
// give access to Rounting API from GetObserver
Get.routing
// check if snackbar is open
Get.isSnackbarOpen
// check if dialog is open
Get.isDialogOpen
// check if bottomsheet is opefeaturyn
Get.isBottomSheetOpen
// remove one route.
Get.removeRoute()
// back repeatedly until the predicate returns true.
Get.until()
// go to next route and remove all the previous routes until the predicate returns true.
Get.offUntil()
// go to next named route and remove all the previous routes until the predicate returns true.
Get.offNamedUntil()
//Check in what platform the app is running
GetPlatform.isAndroid
GetPlatform.isIOS
GetPlatform.isWeb
// Equivalent to the method: MediaQuery.of(context).size.height, but they are immutable.
Get.height
Get.width
// Gives the current context of navigator.
Get.context
// 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 scfeaturyaled) 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.
// param dividedBy (double) optional - default: 1
// param reducedBy (double) optional - default: 0
context.heightTransformer()
context.widthTransformer()
/// similar to MediaQuery.of(context).size
context.mediaQuerySize()
/// similar to MediaQuery.of(context).padding
context.mediaQueryPadding()
/// similar to MediaQuery.of(context).viewPadding
context.mediaQueryViewPadding()
/// similar to MediaQuery.of(context).viewInsets;
context.mediaQueryViewInsets()
/// similar to MediaQuery.of(context).orientation;
context.orientation()
/// check if device is on landscape mode
context.isLandscape()
/// check if device is on portrait mode
context.isPortrait()
/// similar to MediaQuery.of(context).devicePixelRatio;
context.devicePixelRatio()
/// similar to MediaQuery.of(context).textScaleFactor;
context.textScaleFactor()
/// get the shortestSide from screen
context.mediaQueryShortestSide()
/// True if width be larger thfeaturyan 800
context.showNavbar()
/// True if the shortestSide is smaller than 600p
context.isPhone()
/// True if the shortestSide is largest than 600p
context.isSmallTablet()
/// True if the shortestSide is largest than 720p
context.isLargeTablet()
/// True if the current device is Tablet
context.isTablet()
```
### Opcjonalne globalne ustawienia i manualna konfiguracja
GetMaterialApp konfiguruje wszystko za Ciebie, ale jeśli chcesz możesz konfigurować Get manualnie.
```dart
MaterialApp(
navigatorKey: Get.key,
navigatorObservers: [GetObserver()],
);
```
Będziesz mógł używać swojego Midware z GetObserver, nie wpływa to na nic.
```dart
MaterialApp(
navigatorKey: Get.key,
navigatorObservers: [
GetObserver(MiddleWare.observer) // Here
],
);
```
Mozesz stworzyć globalne ustawienia dla Get. Tylko dodaj Get.config do swojego kodu przed użyciem routów, lub bezpośrednio w GetMaterialApp
```dart
GetMaterialApp(
enableLog: true,
defaultTransition: Transition.fade,
opaqueRoute: Get.isOpaqueRouteDefault,
popGesture: Get.isPopGestureEnable,
transitionDuration: Get.defaultDurationTransition,
defaultGlobalState: Get.defaultGlobalState,https://github.com/jonataslaw/ge
);
Get.config(
enableLog = true,
defaultPopGesture = true,
defaultTransition = Transitions.cupertino
)
```
## Video tłumaczące inne funkcjonalności GetX
Amateur Coder nagrał niezwykły film tłumaczący powyższe zagadnienia!
Link: [GetX Other Features](https://youtu.be/ttQtlX_Q0eU)
# Zmiany od 2.0
1- Typy Rx:
| Przed | Po |
| ------- | ---------- |
| StringX | `RxString` |
| IntX | `RxInt` |
| MapX | `RxMax` |
| ListX | `RxList` |
| NumX | `RxNum` |
| DoubleX | `RxDouble` |
RXController i GetBuilder teraz zostały połączone. Nie musisz już pamiętać którego kontrolerachcesz użyć, po prostu korzystaj z GetxController, będzie działać zarówno dla prostego jak i reaktywnego menadżera stanów.
2- NamedRoutes
Wcześniej:
```dart
GetMaterialApp(
namedRoutes: {
'/': GetRoute(page: Home()),
}
)
```
Teraz:
```dart
GetMaterialApp(
getPages: [
GetPage(name: '/', page:()=> Home()),
]
)
```
Po co ta zmiana?
Często może być niezbędnym decydowanie która strona będzie wyswietlana w zależności od parametru, lub tokenu logowania. Wczesniejsze podejscie było nieelastyczne nie pozwalając na to. Zawarcie strony w funkcji zmniejszyło sporzycie RAM-u, ze względu na niealokowanie routów od początku działania aplikacji. Pozwoliło to także na takie podejscie:
```dart
GetStorage box = GetStorage();
GetMaterialApp(
getPages: [
GetPage(name: '/', page:(){
return box.hasData('token') ? Home() : Login();
})
]
)
```
... ...
![](get.png)
*Idiomas: [Inglês](README.md), Português Brasileiro (este arquivo), [Espanhol](README-es.md).*
*Idiomas: [Inglês](README.md), Português Brasileiro (este arquivo), [Espanhol](README-es.md), [Polaco](README.pl.md).*
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
... ... @@ -473,6 +473,22 @@ Get.config(
)
```
É possível redirecionar todas as mensagens de log do GetX. Útil quando se tem um package de logging e vc quer que ele lide com todos os logs
```dart
GetMaterialApp(
enableLog: true,
logWriterCallback: localLogWriter,
);
void localLogWriter(String text, {bool isError = false}) {
// passage a mensagem para seu package de logging favorito aqui
// Obs: mesmo que as mensagens de log estejam desativadas
// com o comando "enableLog: false", as mensagens ainda vão passar por aqui
// Você precisa checar essa config manualmente aqui se quiser respeitá-la
}
```
## Video explanation of Other GetX Features
... ...
... ... @@ -35,7 +35,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.1"
version: "2.5.0-nullsafety"
bloc:
dependency: "direct main"
description:
... ... @@ -49,7 +49,7 @@ packages:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
build:
dependency: transitive
description:
... ... @@ -106,13 +106,20 @@ packages:
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.2"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
version: "1.2.0-nullsafety"
checked_yaml:
dependency: transitive
description:
... ... @@ -120,6 +127,13 @@ packages:
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.1.0-nullsafety"
code_builder:
dependency: transitive
description:
... ... @@ -133,7 +147,7 @@ packages:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.12"
version: "1.15.0-nullsafety.2"
convert:
dependency: transitive
description:
... ... @@ -176,6 +190,13 @@ packages:
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-nullsafety"
fixnum:
dependency: transitive
description:
... ... @@ -297,14 +318,14 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.6"
version: "0.12.10-nullsafety"
meta:
dependency: "direct main"
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
version: "1.3.0-nullsafety.2"
mime:
dependency: transitive
description:
... ... @@ -360,7 +381,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
version: "1.8.0-nullsafety"
pedantic:
dependency: transitive
description:
... ... @@ -456,21 +477,21 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
version: "1.10.0-nullsafety"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
stream_transform:
dependency: transitive
description:
... ... @@ -484,21 +505,21 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "1.1.0-nullsafety"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0-nullsafety"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.15"
version: "0.2.19-nullsafety"
timing:
dependency: transitive
description:
... ... @@ -512,7 +533,7 @@ packages:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
version: "1.3.0-nullsafety.2"
uuid:
dependency: "direct main"
description:
... ... @@ -526,7 +547,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.1.0-nullsafety.2"
watcher:
dependency: transitive
description:
... ... @@ -556,5 +577,5 @@ packages:
source: hosted
version: "2.2.1"
sdks:
dart: ">=2.7.0 <3.0.0"
dart: ">=2.10.0-0.0.dev <2.10.0"
flutter: ">=1.16.0"
... ...
... ... @@ -476,7 +476,7 @@ Get.bottomSheet(
),
],
),
);
)
);
```
... ...
... ... @@ -265,7 +265,7 @@ final list = List<User>().obs;
```dart
Text(title.value), // String need to have .value in front of it
ListView.builder (
itemCount: list.lenght // lists don't need it
itemCount: list.length // lists don't need it
)
```
... ...
... ... @@ -476,7 +476,7 @@ Get.bottomSheet(
),
],
),
);
)
);
```
... ...
... ... @@ -516,7 +516,7 @@ final list = List<User>().obs;
```dart
ListView.builder (
itemCount: list.lenght
itemCount: list.length
)
```
... ...
... ... @@ -20,7 +20,7 @@ Em vez de instanciar sua classe dentro da classe que você está usando, você e
Para que então você possa usar seu controller (ou uma classe Bloc) normalmente
**Tip:** O gerenciamento de dependência do get é desaclpado de outras partes do package, então se por exemplo seu aplicativo já está usando um outro gerenciador de estado (qualquer um, não importa), você não precisa de reescrever tudo, pode simplesmente usar só a injeção de dependência sem problemas
**Tip:** O gerenciamento de dependência do get é desacoplado de outras partes do package, então se por exemplo seu aplicativo já está usando um outro gerenciador de estado (qualquer um, não importa), você não precisa de reescrever tudo, pode simplesmente usar só a injeção de dependência sem problemas
```dart
controller.fetchApi();
... ... @@ -71,11 +71,11 @@ Para remover a instância do Get:
Get.delete<Controller>();
```
## Opções
## Métodos de instanciamento.
Quando você usa Get.put, lazyPut e putAsync, existe algumas opções que você pode alterar se quiser
Apesar do Get já entregar configurações muito boas para uso, é possível refiná-las ainda mais para que sejam de utilidade ainda maior para você programador. Os métodos e seus parâmetros configuráveis são:
- No Get.put():
- Get.put():
```dart
Get.put<S>(
... ... @@ -95,17 +95,12 @@ Get.put<S>(
// padrão: false
bool permanent = false,
// opcional: permite que depois de usar uma classe abstrata num teste,
// trocar por outra e continuar com o teste
// padrão: false
bool overrideAbstract = false,
// opcional: permite criar a dependência usando uma função em vez da dependênia em si
FcBuilderFunc<S> builder,
)
```
- No Get.lazyPut:
- Get.lazyPut:
```dart
Get.lazyPut<S>(
... ... @@ -126,7 +121,7 @@ Get.lazyPut<S>(
)
```
- No Get.putAsync:
- Get.putAsync:
```dart
Get.putAsync<S>(
... ... @@ -143,6 +138,44 @@ Get.putAsync<S>(
bool permanent = false
```
- Get.create:
```dart
Get.create<S>(
// Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado
// Exemplo: Get.create<YourClass>(() => YourClass())
FcBuilderFunc<S> builder,
// opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe.
// Útil caso você tenha uma lista em que cada item precise de um controller próprio
// precisa ser uma string única. Apenas mudou o nome de tag para name.
String name,
// opcional: igual ao Get.put(), usado quando você precisa manter a instância ativa no app inteiro. A diferença
// é que com Get.create o permanent está habilitado por padrão
bool permanent = true
```
### Diferenças entre os métodos:
Primeiramente, vamos falar das variáveis `_factory` e `_singl`. Ambas são essenciais no processo de criação e uso de suas dependências, pois é através delas que podemos armazenar, apagar, recriar nossas instâncias.
Primeiro, vamos falar do `fenix` do Get.lazyPut e o `permanent` dos outros métodos.
- O `fenix` diz respeito ao armazenamento da instância. Quando você manipula os parâmetros `fenix` ou `smartManagement` para não perder as instâncias da sua dependência, elas serão salvas na para serem chamadas posteriormente.
- O `permanent` diz respeito ao uso. Se a instância permanece ativa, ou se é apagada, quando não está em uso na tela.
A diferença fundamental entre `permanent` e `fenix` está em como você quer armazenar as suas instâncias. Reforçando: por padrão, o Get apaga as instâncias quando elas não estão em uso (Digamos que a tela 1 tenha o controlador A e tela 2, controlador B. Ao mover-se de 1 para 2, o controlador A perde o uso e portanto é apagado), mas se você optar por algo `permanent: true`, então ela não se perde nessa transição - o que é muito útil para serviços que você quer manter rodando na aplicação inteira. Já o `fenix`, é para serviços que você não se preocupa em perder por uma tela ou outra, mas quando você precisar chamar o serviço, você espera que ele "retorne das cinzas" (`fenix: true`), criando uma nova instância.
Prosseguindo com as diferenças entre os métodos:
- Get.put e Get.putAsync seguem a mesma ordem de criação, com a diferença que o Async opta por aplicar um método assíncrono: Esses dois métodos criam e já inicializam a instância. Esta é inserida diretamente na memória, através do método interno `insert` com os parâmetros `permanent: false` e `isSingleton: true` (esse parâmetro `isSingleton` serve apenas para dizer se é para utilizar a dependência colocada em `dependency`, ou se é para usar a dependência colocada no `FcBuilderFunc`). Depois disso, é chamado o `Get.find` que imediatamente inicializa as instâncias que estão na memória.
- Get.create: Como o nome indica, você vai "criar" a sua dependência! Similar ao `Get.put`, ela também chama o método interno `insert` para instanciamento. Contudo, `permanent` e `isSingleton` passam a ser `true` e `false` (Como estamos "criando" a nossa dependência, não tem como ela ser um Singleton de algo, logo, `false`). E por ser `permanent: true`, temos por padrão o benefício de não se perder entre telas! Além disso, não é chamado o `Get.find`, logo ela fica esperando ser chamada para ser usada. Ele é criado dessa forma para aproveitar o uso do parâmetro `permanent`, já que, vale ressaltar, o Get.create foi criado com o objetivo de criar instâncias não compartilhadas, mas que não se perdem, como por exemplo um botão em um listView, que você quer uma instância única para aquela lista - por conta disso, o Get.create deve ser usado em conjunto com o GetWidget.
- Get.lazyPut: Como o nome dá a entender, é um processo preguiçoso (lazy). A instância é criada, mas ela não é chamada para uso logo em seguida, ela fica aguardando ser chamada. Diferente dos outros métodos, o `insert` não é chamado. Ao invés disso, a instância é inserida em outra parte na memória, uma parte responsável por dizer se a instância pode ser recriada ou não, vamos chamá-la de "fábrica". Se queremos criar algo para ser chamado só depois, não vamos misturá-lo com as coisas que estão sendo usadas agora. E é aqui que entra a mágica do `fenix`. Se você optou por deixar `fenix: false`, e seu `smartManagement` não for `keepFactory`, então ao usar o `Get.find` a instância passa da "fábrica" para a área comum das instância. Em seguinda, por padrão é removida da "fábrica". Agora, se você optou por `fenix: true`, a instância continua a existir nessa parte dedicada, mesmo indo para a área comum, para ser chamada futuramente caso precise.
## Bindings
Um dos grandes diferenciais desse package, talvez, seja a possibilidade de integração total com rotas, gerenciador de estado e gerenciador de dependências.
... ...
... ... @@ -416,7 +416,7 @@ Você também não precisa usar `.value` com listas, a api dart nos permitiu rem
final list = List<Usuario>().obs;
ListView.builder (
itemCount: list.lenght
itemCount: list.length
)
```
... ...
{
"configVersion": 2,
"packages": [
{
"name": "async",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.4.2",
"packageUri": "lib/",
"languageVersion": "2.2"
},
{
"name": "boolean_selector",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.0.0",
"packageUri": "lib/",
"languageVersion": "2.4"
},
{
"name": "characters",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.0.0",
"packageUri": "lib/",
"languageVersion": "2.6"
},
{
"name": "charcode",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.3",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "clock",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.0.1",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "collection",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.14.13",
"packageUri": "lib/",
"languageVersion": "2.3"
},
{
"name": "dio",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/dio-3.0.9",
"packageUri": "lib/",
"languageVersion": "2.4"
},
{
"name": "fake_async",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.1.0",
"packageUri": "lib/",
"languageVersion": "2.2"
},
{
"name": "flutter",
"rootUri": "file:///opt/flutter/packages/flutter",
"packageUri": "lib/",
"languageVersion": "2.9"
},
{
"name": "flutter_test",
"rootUri": "file:///opt/flutter/packages/flutter_test",
"packageUri": "lib/",
"languageVersion": "2.2"
},
{
"name": "get",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/get-3.2.2",
"packageUri": "lib/",
"languageVersion": "2.6"
},
{
"name": "http_parser",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.4",
"packageUri": "lib/",
"languageVersion": "2.3"
},
{
"name": "matcher",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.8",
"packageUri": "lib/",
"languageVersion": "2.4"
},
{
"name": "meta",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.1.8",
"packageUri": "lib/",
"languageVersion": "1.12"
},
{
"name": "path",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.7.0",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "sky_engine",
"rootUri": "file:///opt/flutter/bin/cache/pkg/sky_engine",
"packageUri": "lib/",
"languageVersion": "1.11"
},
{
"name": "source_span",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.7.0",
"packageUri": "lib/",
"languageVersion": "2.6"
},
{
"name": "stack_trace",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.5",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "stream_channel",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "string_scanner",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "term_glyph",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0",
"packageUri": "lib/",
"languageVersion": "1.8"
},
{
"name": "test_api",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.17",
"packageUri": "lib/",
"languageVersion": "2.7"
},
{
"name": "typed_data",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.2.0",
"packageUri": "lib/",
"languageVersion": "2.4"
},
{
"name": "vector_math",
"rootUri": "file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.0.8",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "get_state",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "2.7"
}
],
"generated": "2020-07-14T09:09:42.984811Z",
"generator": "pub",
"generatorVersion": "2.9.0-21.2.beta"
}
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
... ...
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 7c6f9dd2396dfe7deb6fd11edc12c10786490083
channel: dev
project_type: app
... ...
# Generated by pub on 2020-07-14 06:09:42.955823.
async:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.4.2/lib/
boolean_selector:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.0.0/lib/
characters:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.0.0/lib/
charcode:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.3/lib/
clock:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.0.1/lib/
collection:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.14.13/lib/
dio:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/dio-3.0.9/lib/
fake_async:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.1.0/lib/
flutter:file:///opt/flutter/packages/flutter/lib/
flutter_test:file:///opt/flutter/packages/flutter_test/lib/
get:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/get-3.2.2/lib/
http_parser:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.4/lib/
matcher:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.8/lib/
meta:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.1.8/lib/
path:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.7.0/lib/
sky_engine:file:///opt/flutter/bin/cache/pkg/sky_engine/lib/
source_span:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.7.0/lib/
stack_trace:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.9.5/lib/
stream_channel:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.0.0/lib/
string_scanner:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/
term_glyph:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/
test_api:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.17/lib/
typed_data:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.2.0/lib/
vector_math:file:///opt/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.0.8/lib/
get_state:lib/
# example
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
... ...
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:get_state/home/controllers/home_controller.dart';
import 'package:get_state/home/data/home_provider.dart';
import 'package:get_state/home/data/home_repository.dart';
import '../controllers/home_controller.dart';
import '../data/home_provider.dart';
import '../data/home_repository.dart';
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<HomeController>(() {
final homeProvider = HomeProvider();
final homeRepository = HomeRepository(homeProvider);
return HomeController(homeRepository);
Get.put(Dio());
Get.put(HomeProvider(dio: Get.find()));
Get.put(HomeRepository(homeProvider: Get.find()));
return HomeController(homeRepository: Get.find());
});
}
}
... ...
import 'package:get/get.dart';
import 'package:get_state/home/data/home_model.dart';
import 'package:get_state/home/data/home_repository.dart';
import '../data/home_model.dart';
import '../data/home_repository.dart';
class HomeController extends GetxController {
HomeController(this.homeRepository);
HomeController({this.homeRepository});
final HomeRepository homeRepository;
Rx<ApiModel> data = Rx<ApiModel>();
... ...
import 'package:dio/dio.dart';
import 'package:get_state/home/data/home_model.dart';
import 'package:flutter/foundation.dart';
import 'home_model.dart';
class HomeProvider {
Future<ApiModel> fetchData() async {
abstract class IHomeProvider {
Future<ApiModel> get();
Future<ApiModel> post(Map<String, dynamic> data);
Future<ApiModel> put(Map<String, dynamic> data);
Future<ApiModel> delete(int id);
}
class HomeProvider implements IHomeProvider {
final Dio dio;
HomeProvider({@required this.dio});
Future<ApiModel> get() async {
try {
final response = await Dio().get("https://api.covid19api.com/summary");
final response = await dio.get("https://api.covid19api.com/summary");
return ApiModel.fromJson(response.data);
} catch (e) {
print(e.toString());
return ApiModel();
return null;
}
}
@override
Future<ApiModel> post(Map<String, dynamic> data) {
throw UnimplementedError();
}
@override
Future<ApiModel> put(Map<String, dynamic> data) {
throw UnimplementedError();
}
@override
Future<ApiModel> delete(int id) {
throw UnimplementedError();
}
}
... ...
import 'package:get_state/home/data/home_provider.dart';
import 'package:get_state/home/data/home_model.dart';
import 'home_model.dart';
import 'home_provider.dart';
class HomeRepository {
HomeRepository(this.homeProvider);
HomeRepository({this.homeProvider});
final HomeProvider homeProvider;
Future<ApiModel> getData() async {
return homeProvider.fetchData();
return homeProvider.get();
}
}
... ...
... ... @@ -10,6 +10,8 @@ void main() {
GetMaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/',
enableLog: true,
// logWriterCallback: localLogWriter,
getPages: [
GetPage(name: '/', page: () => HomePage(), binding: HomeBinding()),
GetPage(name: '/country', page: () => CountryPage()),
... ... @@ -18,3 +20,8 @@ void main() {
),
);
}
// Sample of abstract logging function
void localLogWriter(String text, {bool isError = false}) {
print('** ' + text + ' [' + isError.toString() + ']');
}
... ...
include app_configuration.mk
# Default build type.
BUILD=debug
FLUTTER_MANAGED_DIR=flutter
FLUTTER_EPHEMERAL_DIR=$(FLUTTER_MANAGED_DIR)/ephemeral
# Configuration provided via flutter tool.
FLUTTER_CONFIG_FILE=$(FLUTTER_EPHEMERAL_DIR)/generated_config.mk
include $(FLUTTER_CONFIG_FILE)
# Dependency locations
FLUTTER_APP_DIR=$(CURDIR)/..
FLUTTER_APP_BUILD_DIR=$(FLUTTER_APP_DIR)/build
OUT_DIR=$(FLUTTER_APP_BUILD_DIR)/linux
OBJ_DIR=$(OUT_DIR)/obj/$(BUILD)
# Libraries
FLUTTER_LIB_NAME=flutter_linux_glfw
FLUTTER_LIB=$(FLUTTER_EPHEMERAL_DIR)/lib$(FLUTTER_LIB_NAME).so
# Tools
FLUTTER_BIN=$(FLUTTER_ROOT)/bin/flutter
LINUX_BUILD=$(FLUTTER_ROOT)/packages/flutter_tools/bin/tool_backend.sh
# Resources
ICU_DATA_NAME=icudtl.dat
ICU_DATA_SOURCE=$(FLUTTER_EPHEMERAL_DIR)/$(ICU_DATA_NAME)
FLUTTER_ASSETS_NAME=flutter_assets
FLUTTER_ASSETS_SOURCE=$(FLUTTER_APP_BUILD_DIR)/$(FLUTTER_ASSETS_NAME)
# Bundle structure
BUNDLE_OUT_DIR=$(OUT_DIR)/$(BUILD)
BUNDLE_DATA_DIR=$(BUNDLE_OUT_DIR)/data
BUNDLE_LIB_DIR=$(BUNDLE_OUT_DIR)/lib
BIN_OUT=$(BUNDLE_OUT_DIR)/$(BINARY_NAME)
ICU_DATA_OUT=$(BUNDLE_DATA_DIR)/$(ICU_DATA_NAME)
FLUTTER_LIB_OUT=$(BUNDLE_LIB_DIR)/$(notdir $(FLUTTER_LIB))
ALL_LIBS_OUT=$(FLUTTER_LIB_OUT) \
$(foreach lib,$(EXTRA_BUNDLED_LIBRARIES),$(BUNDLE_LIB_DIR)/$(notdir $(lib)))
# Add relevant code from the wrapper library, which is intended to be statically
# built into the client.
# Use abspath for the wrapper root, which can contain relative paths; the
# intermediate build files will be based on the source path, which will cause
# issues if they start with one or more '../'s.
WRAPPER_ROOT=$(abspath $(FLUTTER_EPHEMERAL_DIR)/cpp_client_wrapper_glfw)
WRAPPER_SOURCES= \
$(WRAPPER_ROOT)/flutter_window_controller.cc \
$(WRAPPER_ROOT)/plugin_registrar.cc \
$(WRAPPER_ROOT)/engine_method_result.cc
# Use abspath for extra sources, which may also contain relative paths (see
# note above about WRAPPER_ROOT).
SOURCES=main.cc window_configuration.cc \
flutter/generated_plugin_registrant.cc \
$(WRAPPER_SOURCES) $(abspath $(EXTRA_SOURCES))
# Headers
WRAPPER_INCLUDE_DIR=$(WRAPPER_ROOT)/include
INCLUDE_DIRS=$(FLUTTER_EPHEMERAL_DIR) $(WRAPPER_INCLUDE_DIR)
# Build settings
ifneq ($(strip $(SYSTEM_LIBRARIES)),)
EXTRA_CPPFLAGS+=$(patsubst -I%,-isystem%,$(shell pkg-config --cflags $(SYSTEM_LIBRARIES)))
EXTRA_LDFLAGS+=$(shell pkg-config --libs $(SYSTEM_LIBRARIES))
endif
CXX=clang++
CPPFLAGS.release=-DNDEBUG
CPPFLAGS.profile=$(CPPFLAGS.release)
CXXFLAGS.release=-O2
CXXFLAGS.profile=$(CXXFLAGS.release)
CXXFLAGS=-std=c++14 -Wall -Werror $(CXXFLAGS.$(BUILD)) $(EXTRA_CXXFLAGS)
CPPFLAGS=$(patsubst %,-I%,$(INCLUDE_DIRS)) \
$(CPPFLAGS.$(BUILD)) $(EXTRA_CPPFLAGS)
LDFLAGS=-L$(BUNDLE_LIB_DIR) \
-l$(FLUTTER_LIB_NAME) \
$(EXTRA_LDFLAGS) \
-Wl,-rpath=\$$ORIGIN/lib
# Intermediate files.
OBJ_FILES=$(SOURCES:%.cc=$(OBJ_DIR)/%.o)
DEPENDENCY_FILES=$(OBJ_FILES:%.o=%.d)
# Targets
.PHONY: all
all: $(BIN_OUT) bundle
# Add the plugin targets, and their associated settings.
include $(FLUTTER_MANAGED_DIR)/generated_plugins.mk
EXTRA_BUNDLED_LIBRARIES+=$(PLUGIN_LIBRARIES)
EXTRA_LDFLAGS+=$(PLUGIN_LDFLAGS)
EXTRA_CPPFLAGS+=$(PLUGIN_CPPFLAGS)
# This is a phony target because the flutter tool cannot describe
# its inputs and outputs yet.
.PHONY: sync
sync: $(FLUTTER_CONFIG_FILE)
$(LINUX_BUILD) linux-x64 $(BUILD)
.PHONY: bundle
bundle: $(ICU_DATA_OUT) $(ALL_LIBS_OUT) bundleflutterassets
$(BIN_OUT): $(OBJ_FILES) $(ALL_LIBS_OUT)
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OBJ_FILES) $(LDFLAGS) -o $@
$(WRAPPER_SOURCES) $(FLUTTER_LIB) $(ICU_DATA_SOURCE) $(FLUTTER_ASSETS_SOURCE) \
$(PLUGIN_TARGETS): | sync
# Plugin library bundling pattern.
$(BUNDLE_LIB_DIR)/%: $(OUT_DIR)/%
mkdir -p $(BUNDLE_LIB_DIR)
cp $< $@
$(FLUTTER_LIB_OUT): $(FLUTTER_LIB)
mkdir -p $(@D)
cp $< $@
$(ICU_DATA_OUT): $(ICU_DATA_SOURCE)
mkdir -p $(@D)
cp $< $@
-include $(DEPENDENCY_FILES)
$(OBJ_DIR)/%.o : %.cc | sync
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -c $< -o $@
# Fully re-copy the assets directory on each build to avoid having to keep a
# comprehensive list of all asset files here, which would be fragile to changes
# in other files (e.g., adding a new font to pubspec.yaml).
.PHONY: bundleflutterassets
bundleflutterassets: $(FLUTTER_ASSETS_SOURCE)
mkdir -p $(BUNDLE_DATA_DIR)
rsync -rpu --delete $(FLUTTER_ASSETS_SOURCE) $(BUNDLE_DATA_DIR)
.PHONY: clean
clean:
rm -rf $(OUT_DIR); \
cd $(FLUTTER_APP_DIR); \
$(FLUTTER_BIN) clean
# This file contains variables that applications are likely to need to
# change, to isolate them from the main Makefile where the build rules are still
# in flux. This should simplify re-creating the runner while preserving local
# changes.
# Executable name.
BINARY_NAME=get_state
# Any extra source files to build.
EXTRA_SOURCES=
# Paths of any additional libraries to be bundled in the output directory.
EXTRA_BUNDLED_LIBRARIES=
# Extra flags (e.g., for library dependencies).
SYSTEM_LIBRARIES=
EXTRA_CXXFLAGS=
EXTRA_CPPFLAGS=
EXTRA_LDFLAGS=
\ No newline at end of file
//
// Generated file. Do not edit.
//
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}
//
// Generated file. Do not edit.
//
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
# Plugins to include in the build.
GENERATED_PLUGINS=\
GENERATED_PLUGINS_DIR=flutter/ephemeral/.plugin_symlinks
# A plugin library name plugin name with _plugin appended.
GENERATED_PLUGIN_LIB_NAMES=$(foreach plugin,$(GENERATED_PLUGINS),$(plugin)_plugin)
# Variables for use in the enclosing Makefile. Changes to these names are
# breaking changes.
PLUGIN_TARGETS=$(GENERATED_PLUGINS)
PLUGIN_LIBRARIES=$(foreach plugin,$(GENERATED_PLUGIN_LIB_NAMES),\
$(OUT_DIR)/lib$(plugin).so)
PLUGIN_LDFLAGS=$(patsubst %,-l%,$(GENERATED_PLUGIN_LIB_NAMES))
PLUGIN_CPPFLAGS=$(foreach plugin,$(GENERATED_PLUGINS),\
-I$(GENERATED_PLUGINS_DIR)/$(plugin)/linux)
# Targets
# Implicit rules don't match phony targets, so list plugin builds explicitly.
.PHONY: $(GENERATED_PLUGINS)
$(GENERATED_PLUGINS):
make -C $(GENERATED_PLUGINS_DIR)/$@/linux \
OUT_DIR=$(OUT_DIR) \
FLUTTER_EPHEMERAL_DIR="$(abspath flutter/ephemeral)"
#include <flutter/flutter_window_controller.h>
#include <linux/limits.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <vector>
#include "flutter/generated_plugin_registrant.h"
#include "window_configuration.h"
namespace {
// Returns the path of the directory containing this executable, or an empty
// string if the directory cannot be found.
std::string GetExecutableDirectory() {
char buffer[PATH_MAX + 1];
ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
if (length > PATH_MAX) {
std::cerr << "Couldn't locate executable" << std::endl;
return "";
}
std::string executable_path(buffer, length);
size_t last_separator_position = executable_path.find_last_of('/');
if (last_separator_position == std::string::npos) {
std::cerr << "Unabled to find parent directory of " << executable_path
<< std::endl;
return "";
}
return executable_path.substr(0, last_separator_position);
}
} // namespace
int main(int argc, char **argv) {
// Resources are located relative to the executable.
std::string base_directory = GetExecutableDirectory();
if (base_directory.empty()) {
base_directory = ".";
}
std::string data_directory = base_directory + "/data";
std::string assets_path = data_directory + "/flutter_assets";
std::string icu_data_path = data_directory + "/icudtl.dat";
// Arguments for the Flutter Engine.
std::vector<std::string> arguments;
flutter::FlutterWindowController flutter_controller(icu_data_path);
flutter::WindowProperties window_properties = {};
window_properties.title = kFlutterWindowTitle;
window_properties.width = kFlutterWindowWidth;
window_properties.height = kFlutterWindowHeight;
// Start the engine.
if (!flutter_controller.CreateWindow(window_properties, assets_path,
arguments)) {
return EXIT_FAILURE;
}
RegisterPlugins(&flutter_controller);
// Run until the window is closed.
while (flutter_controller.RunEventLoopWithTimeout(
std::chrono::milliseconds::max())) {
}
return EXIT_SUCCESS;
}
#include "window_configuration.h"
const char *kFlutterWindowTitle = "get_state";
const unsigned int kFlutterWindowWidth = 800;
const unsigned int kFlutterWindowHeight = 600;
#ifndef WINDOW_CONFIGURATION_
#define WINDOW_CONFIGURATION_
// This is a temporary approach to isolate common customizations from main.cpp,
// where the APIs are still in flux. This should simplify re-creating the
// runner while preserving local changes.
//
// Longer term there should be simpler configuration options for common
// customizations like this, without requiring native code changes.
extern const char *kFlutterWindowTitle;
extern const unsigned int kFlutterWindowWidth;
extern const unsigned int kFlutterWindowHeight;
#endif // WINDOW_CONFIGURATION_
... ... @@ -21,49 +21,56 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.1"
version: "2.5.0-nullsafety"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
charcode:
version: "2.1.0-nullsafety"
characters:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
collection:
version: "1.1.0-nullsafety.2"
charcode:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.12"
convert:
version: "1.2.0-nullsafety"
clock:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
crypto:
version: "1.1.0-nullsafety"
collection:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
version: "1.15.0-nullsafety.2"
dio:
dependency: "direct main"
description:
name: dio
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.9"
version: "3.0.10"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety"
flutter:
dependency: "direct main"
description: flutter
... ... @@ -77,10 +84,10 @@ packages:
get:
dependency: "direct main"
description:
name: get
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.2"
path: ".."
relative: true
source: path
version: "3.4.6"
http_parser:
dependency: transitive
description:
... ... @@ -101,35 +108,21 @@ packages:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.6"
version: "0.12.10-nullsafety"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
version: "1.3.0-nullsafety.2"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
version: "1.8.0-nullsafety"
sky_engine:
dependency: transitive
description: flutter
... ... @@ -141,62 +134,55 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
version: "1.8.0-nullsafety"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
version: "1.10.0-nullsafety"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
version: "2.1.0-nullsafety"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
version: "1.1.0-nullsafety"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0-nullsafety"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.15"
version: "0.2.19-nullsafety"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
version: "1.3.0-nullsafety.2"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.6.1"
version: "2.1.0-nullsafety.2"
sdks:
dart: ">=2.7.0 <3.0.0"
dart: ">=2.10.0-0.0.dev <2.10.0"
... ...
... ... @@ -3,7 +3,7 @@ description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
publish_to: "none" # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
... ... @@ -24,10 +24,10 @@ dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
get: ^3.2.2
get:
path: ../
dio: ^3.0.9
dev_dependencies:
... ... @@ -39,23 +39,18 @@ dev_dependencies:
# 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.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/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
... ...

83 KB | W: | H:

26.7 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
export 'src/instance/get_instance.dart';
export 'src/instance/extension_instance.dart';
export 'src/typedefs/typedefs.dart';
export 'src/routes/bindings_interface.dart';
export 'src/navigation/routes/bindings_interface.dart';
... ...
export 'src/routes/custom_transition.dart';
export 'src/routes/transitions_type.dart';
export 'src/routes/get_route.dart';
export 'src/routes/default_route.dart';
export 'src/routes/observers/route_observer.dart';
export 'src/root/root_widget.dart';
export 'src/snackbar/snack_route.dart';
export 'src/bottomsheet/bottomsheet.dart';
export 'src/snackbar/snack.dart';
export 'src/get_main.dart';
export 'src/routes/default_route.dart';
export 'src/root/smart_management.dart';
export 'src/navigation/routes/custom_transition.dart';
export 'src/navigation/routes/transitions_type.dart';
export 'src/navigation/routes/get_route.dart';
export 'src/navigation/routes/default_route.dart';
export 'src/navigation/routes/observers/route_observer.dart';
export 'src/navigation/root/root_widget.dart';
export 'src/navigation/snackbar/snack_route.dart';
export 'src/navigation/bottomsheet/bottomsheet.dart';
export 'src/navigation/snackbar/snack.dart';
export 'src/core/get_main.dart';
export 'src/navigation/routes/default_route.dart';
export 'src/navigation/root/smart_management.dart';
export 'src/navigation/extension_navigation.dart';
... ...
import 'package:flutter/material.dart';
import '../navigation/root/parse_route.dart';
import '../navigation/root/root_controller.dart';
import '../navigation/routes/custom_transition.dart';
import '../navigation/routes/observers/route_observer.dart';
import '../navigation/routes/transitions_type.dart';
import '../../utils.dart';
///Use Get.to instead of Navigator.push, Get.off instead of Navigator.pushReplacement,
///Get.offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
///after them. Example: Get.toNamed, Get.offNamed, and Get.AllNamed.
///To return to the previous screen, use Get.back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
abstract class GetInterface {
bool defaultPopGesture = GetPlatform.isIOS;
bool defaultOpaqueRoute = true;
Transition defaultTransition;
Duration defaultDurationTransition = Duration(milliseconds: 400);
bool defaultGlobalState = true;
RouteSettings settings;
String defaultSeparator = "_";
final routing = Routing();
Map<String, String> parameters = {};
ParseRouteTree routeTree;
CustomTransition customTransition;
GetMaterialController getxController = GetMaterialController();
Locale locale;
Locale fallbackLocale;
GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
Map<int, GlobalKey<NavigatorState>> keys = {};
Map<String, Map<String, String>> translations = {};
}
... ...
import 'package:get/src/core/get_interface.dart';
///Use to instead of Navigator.push, off instead of Navigator.pushReplacement,
///offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
///after them. Example: toNamed, offNamed, and AllNamed.
///To return to the previous screen, use back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
class _GetImpl extends GetInterface {}
// ignore: non_constant_identifier_names
final Get = _GetImpl();
... ...
import 'package:get/instance_manager.dart';
typedef LogWriterCallback = void Function(String text, {bool isError});
void defaultLogWriterCallback(String value, {bool isError = false}) {
if (isError || GetConfig.isLogEnable) print(value);
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'root/root_controller.dart';
import 'routes/bindings_interface.dart';
import 'routes/transitions_type.dart';
import 'snackbar/snack.dart';
///Use Get.to instead of Navigator.push, Get.off instead of Navigator.pushReplacement,
///Get.offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
///after them. Example: Get.toNamed, Get.offNamed, and Get.AllNamed.
///To return to the previous screen, use Get.back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
///
abstract class GetService {
/// It replaces Navigator.push, but needs no context, and it doesn't have the Navigator.push
/// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
/// of rebuilding every app after a route, use opaque = true as the parameter.
Future<T> to<T>(Widget page,
{bool opaque,
Transition transition,
Duration duration,
int id,
bool fullscreenDialog = false,
Object arguments,
Bindings binding,
bool popGesture});
/// It replaces Navigator.pushNamed, but needs no context, and it doesn't have the Navigator.pushNamed
/// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
/// of rebuilding every app after a route, use opaque = true as the parameter.
Future<T> toNamed<T>(String page, {Object arguments, int id});
/// It replaces Navigator.pushReplacementNamed, but needs no context.
Future<T> offNamed<T>(String page, {Object arguments, int id});
/// It replaces Navigator.popUntil, but needs no context.
void until(RoutePredicate predicate, {int id});
/// It replaces Navigator.pushAndRemoveUntil, but needs no context.
Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id});
/// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context.
Future<T> offNamedUntil<T>(String page, RoutePredicate predicate,
{int id, Object arguments});
/// It replaces Navigator.popAndPushNamed, but needs no context.
Future<T> offAndToNamed<T>(String page,
{Object arguments, int id, dynamic result});
/// It replaces Navigator.removeRoute, but needs no context.
void removeRoute(Route<dynamic> route, {int id});
/// It replaces Navigator.pushNamedAndRemoveUntil, but needs no context.
Future<T> offAllNamed<T>(String newRouteName,
{RoutePredicate predicate, Object arguments, int id});
bool get isOverlaysOpen;
bool get isOverlaysClosed;
/// It replaces Navigator.pop, but needs no context.
void back({dynamic result, bool closeOverlays = false, int id});
/// It will close as many screens as you define. Times must be> 0;
void close(int times, [int id]);
/// It replaces Navigator.pushReplacement, but needs no context, and it doesn't have the Navigator.pushReplacement
/// routes rebuild bug present in Flutter. If for some strange reason you want the default behavior
/// of rebuilding every app after a route, use opaque = true as the parameter.
Future<T> off<T>(Widget page,
{bool opaque = false,
Transition transition,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
Duration duration});
/// It replaces Navigator.pushAndRemoveUntil, but needs no context
Future<T> offAll<T>(Widget page,
{RoutePredicate predicate,
bool opaque = false,
bool popGesture,
int id,
Object arguments,
Bindings binding,
bool fullscreenDialog = false,
Transition transition});
/// Show a dialog
Future<T> dialog<T>(
Widget child, {
bool barrierDismissible = true,
bool useRootNavigator = true,
// RouteSettings routeSettings
});
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
String barrierLabel = "Dismiss",
bool barrierDismissible = true,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
});
Future<T> defaultDialog<T>({
String title = "Alert",
Widget content,
VoidCallback onConfirm,
VoidCallback onCancel,
VoidCallback onCustom,
Color cancelTextColor,
Color confirmTextColor,
String textConfirm,
String textCancel,
String textCustom,
Widget confirm,
Widget cancel,
Widget custom,
Color backgroundColor,
Color buttonColor,
String middleText = "Dialog made in 3 lines of code",
double radius = 20.0,
List<Widget> actions,
});
Future<T> bottomSheet<T>(
Widget bottomsheet, {
Color backgroundColor,
double elevation,
ShapeBorder shape,
Clip clipBehavior,
Color barrierColor,
bool ignoreSafeArea,
bool isScrollControlled = false,
bool useRootNavigator = false,
bool isDismissible = true,
bool enableDrag = true,
});
void rawSnackbar(
{String title,
String message,
Widget titleText,
Widget messageText,
Widget icon,
bool instantInit = true,
bool shouldIconPulse = true,
double maxWidth,
EdgeInsets margin = const EdgeInsets.all(0.0),
EdgeInsets padding = const EdgeInsets.all(16),
double borderRadius = 0.0,
Color borderColor,
double borderWidth = 1.0,
Color backgroundColor = const Color(0xFF303030),
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
Duration duration = const Duration(seconds: 3),
bool isDismissible = true,
SnackDismissDirection dismissDirection = SnackDismissDirection.VERTICAL,
bool showProgressIndicator = false,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackPosition snackPosition = SnackPosition.BOTTOM,
SnackStyle snackStyle = SnackStyle.FLOATING,
Curve forwardAnimationCurve = Curves.easeOutCirc,
Curve reverseAnimationCurve = Curves.easeOutCirc,
Duration animationDuration = const Duration(seconds: 1),
SnackStatusCallback onStatusChanged,
double barBlur = 0.0,
double overlayBlur = 0.0,
Color overlayColor = Colors.transparent,
Form userInputForm});
void snackbar(String title, String message,
{Color colorText,
Duration duration,
/// with instantInit = false you can put Get.snackbar on initState
bool instantInit = true,
SnackPosition snackPosition,
Widget titleText,
Widget messageText,
Widget icon,
bool shouldIconPulse,
double maxWidth,
EdgeInsets margin,
EdgeInsets padding,
double borderRadius,
Color borderColor,
double borderWidth,
Color backgroundColor,
Color leftBarIndicatorColor,
List<BoxShadow> boxShadows,
Gradient backgroundGradient,
FlatButton mainButton,
OnTap onTap,
bool isDismissible,
bool showProgressIndicator,
SnackDismissDirection dismissDirection,
AnimationController progressIndicatorController,
Color progressIndicatorBackgroundColor,
Animation<Color> progressIndicatorValueColor,
SnackStyle snackStyle,
Curve forwardAnimationCurve,
Curve reverseAnimationCurve,
Duration animationDuration,
double barBlur,
double overlayBlur,
Color overlayColor,
Form userInputForm});
/// INSTANCE MANAGER
GetMaterialController getxController;
void changeTheme(ThemeData theme);
void changeThemeMode(ThemeMode themeMode);
GlobalKey<NavigatorState> addKey(GlobalKey<NavigatorState> newKey);
GlobalKey<NavigatorState> key;
GlobalKey<NavigatorState> nestedKey(int key);
GlobalKey<NavigatorState> global(int k);
//////////// INSTANCE MANAGER
// setParameter(Map<String, String> param);
/// give current arguments
Object get arguments;
/// give current arguments
Map<String, String> get parameters;
/// give name from current route
String get currentRoute;
/// give name from previous route
String get previousRoute;
/// check if snackbar is open
bool get isSnackbarOpen;
/// check if dialog is open
bool get isDialogOpen;
/// check if bottomsheet is open
bool get isBottomSheetOpen;
/// check a raw current route
Route<dynamic> get rawRoute;
/// give access to currentContext
BuildContext get context;
/// give access to current Overlay Context
BuildContext get overlayContext;
/// give access to Theme.of(context)
ThemeData get theme;
/// give access to TextTheme.of(context)
TextTheme get textTheme;
/// give access to Mediaquery.of(context)
MediaQueryData get mediaQuery;
/// Check if dark mode theme is enable
bool get isDarkMode;
/// Check if dark mode theme is enable on platform on android Q+
bool get isPlatformDarkMode;
/// give access to Theme.of(context).iconTheme.color
Color get iconColor;
/// give access to Focus.of(context).iconTheme.color
FocusNode get focusScope;
/// give access to MediaQuery.of(context).size.height
double get height;
/// give access to MediaQuery.of(context).size.width
double get width;
}
import 'package:get/src/typedefs/typedefs.dart';
import '../get_main.dart';
import 'package:get/src/core/get_interface.dart';
import 'get_instance.dart';
extension Inst on GetImpl {
extension Inst on GetInterface {
void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
return GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
}
... ... @@ -19,15 +18,9 @@ extension Inst on GetImpl {
GetInstance().find<S>(tag: tag, instance: instance);
S put<S>(S dependency,
{String tag,
bool permanent = false,
bool overrideAbstract = false,
FcBuilderFunc<S> builder}) =>
GetInstance().put<S>(dependency,
tag: tag,
permanent: permanent,
overrideAbstract: overrideAbstract,
builder: builder);
{String tag, bool permanent = false, FcBuilderFunc<S> builder}) =>
GetInstance()
.put<S>(dependency, tag: tag, permanent: permanent, builder: builder);
bool reset({bool clearFactory = true, bool clearRouteBindings = true}) =>
GetInstance().reset(
... ... @@ -37,5 +30,5 @@ extension Inst on GetImpl {
Future<bool> delete<S>({String tag, String key}) async =>
GetInstance().delete<S>(tag: tag, key: key);
bool isRegistred<S>({String tag}) => GetInstance().isRegistred<S>(tag: tag);
bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag);
}
... ...
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/rx/rx_interface.dart';
import 'package:get/src/typedefs/typedefs.dart';
import 'package:get/src/core/log.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'package:get/src/utils/queue/get_queue.dart';
class GetConfig {
//////////// INSTANCE MANAGER
static Map<dynamic, dynamic> _singl = {};
static Map<dynamic, Lazy> _factory = {};
static Map<String, String> routesKey = {};
static SmartManagement smartManagement = SmartManagement.full;
static bool isLogEnable = true;
static LogWriterCallback log = defaultLogWriterCallback;
static String currentRoute;
}
... ... @@ -23,13 +21,17 @@ class GetInstance {
if (_getInstance == null) _getInstance = GetInstance._();
return _getInstance;
}
GetInstance._();
const GetInstance._();
static GetInstance _getInstance;
static Map<dynamic, dynamic> _singl = {};
static Map<dynamic, Lazy> _factory = {};
static Map<String, String> _routesKey = {};
void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
String key = _getKey(S, tag);
GetConfig._factory.putIfAbsent(key, () => Lazy(builder, fenix));
_factory.putIfAbsent(key, () => Lazy(builder, fenix));
}
Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
... ... @@ -42,13 +44,10 @@ class GetInstance {
S dependency, {
String tag,
bool permanent = false,
bool overrideAbstract = false,
FcBuilderFunc<S> builder,
}) {
_insert(
isSingleton: true,
replace: overrideAbstract,
//?? (("$S" == "${dependency.runtimeType}") == false),
name: tag,
permanent: permanent,
builder: builder ?? (() => dependency));
... ... @@ -73,78 +72,92 @@ class GetInstance {
void _insert<S>({
bool isSingleton,
String name,
bool replace = true,
bool permanent = false,
FcBuilderFunc<S> builder,
}) {
assert(builder != null);
String key = _getKey(S, name);
if (replace) {
GetConfig._singl[key] = FcBuilder<S>(isSingleton, builder, permanent);
} else {
GetConfig._singl.putIfAbsent(
key, () => FcBuilder<S>(isSingleton, builder, permanent));
}
_singl.putIfAbsent(
key, () => FcBuilder<S>(isSingleton, builder, permanent, false));
}
void removeDependencyByRoute(String routeName) async {
Future<void> removeDependencyByRoute(String routeName) async {
List<String> keysToRemove = [];
GetConfig.routesKey.forEach((key, value) {
// if (value == routeName && value != null) {
_routesKey.forEach((key, value) {
if (value == routeName) {
keysToRemove.add(key);
}
});
keysToRemove.forEach((element) async {
await delete(key: element);
});
keysToRemove.forEach((element) {
GetConfig.routesKey?.remove(element);
_routesKey?.remove(element);
});
keysToRemove.clear();
}
bool isRouteDependecyNull<S>({String name}) {
return (GetConfig.routesKey[_getKey(S, name)] == null);
}
bool isDependencyInit<S>({String name}) {
bool initDependencies<S>({String name}) {
String key = _getKey(S, name);
return GetConfig.routesKey.containsKey(key);
bool isInit = _singl[key].isInit;
if (!isInit) {
startController<S>(tag: name);
_singl[key].isInit = true;
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
registerRouteInstance<S>(tag: name);
}
}
return true;
}
void registerRouteInstance<S>({String tag}) {
GetConfig.routesKey
.putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute);
_routesKey.putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute);
}
S findByType<S>(Type type, {String tag}) {
String key = _getKey(type, tag);
return GetConfig._singl[key].getSependency() as S;
return _singl[key].getDependency() as S;
}
void initController<S>({String tag}) {
void startController<S>({String tag}) {
String key = _getKey(S, tag);
final i = GetConfig._singl[key].getSependency();
final i = _singl[key].getDependency();
if (i is DisposableInterface) {
i.onStart();
if (GetConfig.isLogEnable) print('[GET] $key has been initialized');
GetConfig.log('[GETX] $key has been initialized');
}
}
// S putOrFind<S>(S Function() dep, {String tag}) {
// final key = _getKey(S, tag);
// if (_singl.containsKey(key)) {
// return _singl[key].getDependency() as S;
// } else {
// if (_factory.containsKey(key)) {
// S _value = put<S>((_factory[key].builder() as S), tag: tag);
// if (GetConfig.smartManagement != SmartManagement.keepFactory) {
// if (!_factory[key].fenix) {
// _factory.remove(key);
// }
// }
// return _value;
// }
// return GetInstance().put(dep(), tag: tag);
// }
// }
/// Find a instance from required class
S find<S>({String tag, FcBuilderFunc<S> instance}) {
String key = _getKey(S, tag);
bool callInit = false;
if (isRegistred<S>(tag: tag)) {
if (!isDependencyInit<S>() &&
GetConfig.smartManagement != SmartManagement.onlyBuilder) {
registerRouteInstance<S>(tag: tag);
callInit = true;
}
FcBuilder builder = GetConfig._singl[key] as FcBuilder;
if (isRegistered<S>(tag: tag)) {
FcBuilder builder = _singl[key] as FcBuilder;
if (builder == null) {
if (tag == null) {
throw "class ${S.toString()} is not register";
... ... @@ -152,69 +165,48 @@ class GetInstance {
throw "class ${S.toString()} with tag '$tag' is not register";
}
}
if (callInit) {
initController<S>(tag: tag);
}
initDependencies<S>(name: tag);
return GetConfig._singl[key].getSependency() as S;
return _singl[key].getDependency() as S;
} else {
if (!GetConfig._factory.containsKey(key))
if (!_factory.containsKey(key))
throw " $S not found. You need call put<$S>($S()) before";
if (GetConfig.isLogEnable)
print('[GET] $S instance was created at that time');
S _value = put<S>(GetConfig._factory[key].builder() as S);
GetConfig.log('[GETX] $S instance was created at that time');
S _value = put<S>(_factory[key].builder() as S);
if (!isDependencyInit<S>() &&
GetConfig.smartManagement != SmartManagement.onlyBuilder) {
registerRouteInstance<S>(tag: tag);
callInit = true;
}
initDependencies<S>(name: tag);
if (GetConfig.smartManagement != SmartManagement.keepFactory) {
if (!GetConfig._factory[key].fenix) {
GetConfig._factory.remove(key);
}
if (GetConfig.smartManagement != SmartManagement.keepFactory &&
!_factory[key].fenix) {
_factory.remove(key);
}
if (callInit) {
initController<S>(tag: tag);
}
return _value;
}
}
/// Remove dependency of [S] on dependency abstraction. For concrete class use delete
void remove<S>({String tag}) {
String key = _getKey(S, tag);
FcBuilder builder = GetConfig._singl[key] as FcBuilder;
final i = builder.dependency;
if (i is DisposableInterface) {
i.onClose();
if (GetConfig.isLogEnable) print('[GET] onClose of $key called');
}
if (builder != null) builder.dependency = null;
if (GetConfig._singl.containsKey(key)) {
print('error on remove $key');
} else {
if (GetConfig.isLogEnable) print('[GET] $key removed from memory');
}
}
String _getKey(Type type, String name) {
return name == null ? type.toString() : type.toString() + name;
}
bool reset({bool clearFactory = true, bool clearRouteBindings = true}) {
if (clearFactory) GetConfig._factory.clear();
if (clearRouteBindings) GetConfig.routesKey.clear();
GetConfig._singl.clear();
if (clearFactory) _factory.clear();
if (clearRouteBindings) _routesKey.clear();
_singl.clear();
return true;
}
static GetQueue queue = GetQueue();
// Future<bool> delete<S>({String tag, String key, bool force = false}) async {
// final s = await queue
// .add<bool>(() async => dele<S>(tag: tag, key: key, force: force));
// return s;
// }
/// Delete class instance on [S] and clean memory
Future<bool> delete<S>({String tag, String key}) async {
Future<bool> delete<S>({String tag, String key, bool force = false}) async {
String newKey;
if (key == null) {
newKey = _getKey(S, tag);
... ... @@ -222,39 +214,69 @@ class GetInstance {
newKey = key;
}
if (!GetConfig._singl.containsKey(newKey)) {
print('Instance $newKey not found');
return false;
}
return queue.add<bool>(() async {
if (!_singl.containsKey(newKey)) {
GetConfig.log('[GETX] Instance $newKey already been removed.',
isError: true);
return false;
}
FcBuilder builder = GetConfig._singl[newKey] as FcBuilder;
if (builder.permanent) {
print(
'[GET] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.');
return false;
}
final i = builder.dependency;
FcBuilder builder = _singl[newKey] as FcBuilder;
if (builder.permanent && !force) {
GetConfig.log(
'[GETX] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.',
isError: true);
return false;
}
final i = builder.dependency;
if (i is DisposableInterface) {
await i.onClose();
if (GetConfig.isLogEnable) print('[GET] onClose of $newKey called');
}
if (i is GetxService && !force) {
return false;
}
if (i is DisposableInterface) {
await i.onClose();
GetConfig.log('[GETX] onClose of $newKey called');
}
GetConfig._singl.removeWhere((oldkey, value) => (oldkey == newKey));
if (GetConfig._singl.containsKey(newKey)) {
print('[GET] error on remove object $newKey');
} else {
if (GetConfig.isLogEnable) print('[GET] $newKey deleted from memory');
}
// GetConfig.routesKey?.remove(key);
return true;
_singl.removeWhere((oldKey, value) => (oldKey == newKey));
if (_singl.containsKey(newKey)) {
GetConfig.log('[GETX] error on remove object $newKey', isError: true);
} else {
GetConfig.log('[GETX] $newKey deleted from memory');
}
// _routesKey?.remove(key);
return true;
});
}
/// check if instance is registred
bool isRegistred<S>({String tag}) =>
GetConfig._singl.containsKey(_getKey(S, tag));
/// check if instance is registered
bool isRegistered<S>({String tag}) => _singl.containsKey(_getKey(S, tag));
/// check if instance is prepared
bool isPrepared<S>({String tag}) =>
GetConfig._factory.containsKey(_getKey(S, tag));
bool isPrepared<S>({String tag}) => _factory.containsKey(_getKey(S, tag));
}
typedef FcBuilderFunc<S> = S Function();
typedef FcBuilderFuncAsync<S> = Future<S> Function();
class FcBuilder<S> {
bool isSingleton;
FcBuilderFunc builderFunc;
S dependency;
bool permanent = false;
bool isInit = false;
FcBuilder(this.isSingleton, this.builderFunc, this.permanent, this.isInit);
S getDependency() {
if (isSingleton) {
if (dependency == null) {
dependency = builderFunc() as S;
}
return dependency;
} else {
return builderFunc() as S;
}
}
}
... ...
... ... @@ -16,6 +16,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
@required this.isScrollControlled,
RouteSettings settings,
}) : assert(isScrollControlled != null),
name = "BOTTOMSHEET: ${builder.hashCode}",
assert(isDismissible != null),
assert(enableDrag != null),
super(settings: settings);
... ... @@ -30,6 +31,7 @@ class GetModalBottomSheetRoute<T> extends PopupRoute<T> {
final Color modalBarrierColor;
final bool isDismissible;
final bool enableDrag;
final String name;
// remove safearea from top
final bool removeTop;
... ...
import 'package:flutter/widgets.dart';
import '../../../instance_manager.dart';
import '../../../route_manager.dart';
class GetDialogRoute<T> extends PopupRoute<T> {
GetDialogRoute({
@required RoutePageBuilder pageBuilder,
bool barrierDismissible = true,
String barrierLabel,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
RouteSettings settings,
}) : assert(barrierDismissible != null),
widget = pageBuilder,
name = "DIALOG: ${pageBuilder.hashCode}",
_barrierDismissible = barrierDismissible,
_barrierLabel = barrierLabel,
_barrierColor = barrierColor,
_transitionDuration = transitionDuration,
_transitionBuilder = transitionBuilder,
super(settings: settings);
final RoutePageBuilder widget;
@override
bool get barrierDismissible => _barrierDismissible;
final bool _barrierDismissible;
final String name;
@override
void dispose() {
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => GetInstance().removeDependencyByRoute(name));
}
super.dispose();
}
@override
String get barrierLabel => _barrierLabel;
final String _barrierLabel;
@override
Color get barrierColor => _barrierColor;
final Color _barrierColor;
@override
Duration get transitionDuration => _transitionDuration;
final Duration _transitionDuration;
final RouteTransitionsBuilder _transitionBuilder;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return Semantics(
child: widget(context, animation, secondaryAnimation),
scopesRoute: true,
explicitChildNodes: true,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
if (_transitionBuilder == null) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.linear,
),
child: child);
} // Some default transition
return _transitionBuilder(context, animation, secondaryAnimation, child);
}
}
... ...
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/get_interface.dart';
import 'bottomsheet/bottomsheet.dart';
import 'instance/get_instance.dart';
import 'platform/platform.dart';
import 'package:get/src/core/get_interface.dart';
import 'package:get/instance_manager.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/core/log.dart';
import 'dialog/dialog_route.dart';
import 'root/parse_route.dart';
import 'root/root_controller.dart';
import 'routes/bindings_interface.dart';
import 'routes/default_route.dart';
import 'routes/observers/route_observer.dart';
import 'routes/transitions_type.dart';
import 'snackbar/snack.dart';
///Use to instead of Navigator.push, off instead of Navigator.pushReplacement,
///offAll instead of Navigator.pushAndRemoveUntil. For named routes just add "named"
///after them. Example: toNamed, offNamed, and AllNamed.
///To return to the previous screen, use back().
///No need to pass any context to Get, just put the name of the route inside
///the parentheses and the magic will occur.
class GetImpl implements GetService {
bool defaultPopGesture = GetPlatform.isIOS;
bool defaultOpaqueRoute = true;
Transition defaultTransition;
Duration defaultDurationTransition = Duration(milliseconds: 400);
bool defaultGlobalState = true;
RouteSettings settings;
String defaultSeparator = "_";
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather Navigator.push(context, YourRoute());
NavigatorState get navigator => Get.key.currentState;
extension GetNavigation on GetInterface {
/// Pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
... ... @@ -60,19 +44,20 @@ class GetImpl implements GetService {
bool fullscreenDialog = false,
Object arguments,
Bindings binding,
preventDuplicates = true,
bool preventDuplicates = true,
bool popGesture,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
String routename = "/${page.runtimeType.toString()}";
if (preventDuplicates && routename == currentRoute) {
return null;
}
return global(id).currentState.push(
GetPageRoute(
opaque: opaque ?? true,
page: () => page,
routeName: routename,
settings: RouteSettings(
name: '/${page.runtimeType}',
// name: forceRouteName ? '${a.runtimeType}' : '',
arguments: arguments,
),
popGesture: popGesture ?? defaultPopGesture,
... ... @@ -144,27 +129,31 @@ class GetImpl implements GetService {
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog is closed
void until(RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return global(id).currentState.popUntil(predicate);
}
/// Push the given [page], and then pop several [pages] in the stack until
/// Push the given [page], and then pop several pages in the stack until
/// [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Obs: unlike other get methods, this one you need to send a function
/// that returns the widget to the page argument, like this:
/// Get.offUntil( () => HomePage() )
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog is closed
Future<T> offUntil<T>(Route<T> page, RoutePredicate predicate, {int id}) {
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
... ... @@ -180,9 +169,9 @@ class GetImpl implements GetService {
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog is closed
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future<T> offNamedUntil<T>(
... ... @@ -219,13 +208,19 @@ class GetImpl implements GetService {
return global(id).currentState.removeRoute(route);
}
/// Push a named [page] and remove all other pages from stack
/// Push a named [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context, so you can
/// call from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
... ... @@ -278,6 +273,9 @@ class GetImpl implements GetService {
}
/// Close as many routes as defined by [times]
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void close(int times, [int id]) {
if ((times == null) || (times < 1)) {
times = 1;
... ... @@ -323,22 +321,24 @@ class GetImpl implements GetService {
preventDuplicates = true,
Duration duration,
}) {
if (preventDuplicates && '/${page.runtimeType}' == currentRoute) {
String routename = "/${page.runtimeType.toString()}";
if (preventDuplicates && routename == currentRoute) {
return null;
}
return global(id).currentState.pushReplacement(GetPageRoute(
opaque: opaque ?? true,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
settings: RouteSettings(arguments: arguments),
routeName: routename,
fullscreenDialog: fullscreenDialog,
popGesture: popGesture ?? defaultPopGesture,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition));
}
/// Pop all pages in the stack and pushes a new [page] to it
/// Push a [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
... ... @@ -351,9 +351,9 @@ class GetImpl implements GetService {
/// as a [fullscreenDialog],
///
/// [predicate] can be used like this:
/// `Get.until(Get.currentRoute == '/home')`so when you get to home page,
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until(!Get.isDialogOpen())`, to make sure the dialog is closed
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
... ... @@ -379,15 +379,17 @@ class GetImpl implements GetService {
}) {
var route = (Route<dynamic> rota) => false;
String routename = "/${page.runtimeType.toString()}";
return global(id).currentState.pushAndRemoveUntil(
GetPageRoute(
opaque: opaque ?? true,
popGesture: popGesture ?? defaultPopGesture,
page: () => page,
binding: binding,
settings:
RouteSettings(name: '/${page.runtimeType}', arguments: arguments),
settings: RouteSettings(arguments: arguments),
fullscreenDialog: fullscreenDialog,
routeName: routename,
transition: transition ?? defaultTransition,
transitionDuration: duration ?? defaultDurationTransition,
),
... ... @@ -396,44 +398,76 @@ class GetImpl implements GetService {
/// Show a dialog
Future<T> dialog<T>(
Widget child, {
Widget widget, {
bool barrierDismissible = true,
Color barrierColor,
bool useSafeArea = true,
bool useRootNavigator = true,
// RouteSettings routeSettings
RouteSettings routeSettings,
}) {
return showDialog(
assert(widget != null);
assert(barrierDismissible != null);
assert(useSafeArea != null);
assert(useRootNavigator != null);
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context, shadowThemeOnly: true);
return generalDialog(
pageBuilder: (BuildContext buildContext, Animation<double> animation,
Animation<double> secondaryAnimation) {
final Widget pageChild = widget;
Widget dialog = Builder(builder: (BuildContext context) {
return theme != null
? Theme(data: theme, child: pageChild)
: pageChild;
});
if (useSafeArea) {
dialog = SafeArea(child: dialog);
}
return dialog;
},
barrierDismissible: barrierDismissible,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
builder: (_) {
return child;
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: barrierColor ?? Colors.black54,
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
},
useRootNavigator: useRootNavigator,
routeSettings: routeSettings,
);
}
/// Api from showGeneralDialog with no context
Future<T> generalDialog<T>({
@required RoutePageBuilder pageBuilder,
String barrierLabel = "Dismiss",
bool barrierDismissible = true,
bool barrierDismissible = false,
String barrierLabel,
Color barrierColor = const Color(0x80000000),
Duration transitionDuration = const Duration(milliseconds: 200),
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
}) {
return showGeneralDialog(
assert(pageBuilder != null);
assert(useRootNavigator != null);
assert(!barrierDismissible || barrierLabel != null);
return Navigator.of(overlayContext, rootNavigator: useRootNavigator)
.push<T>(GetDialogRoute<T>(
pageBuilder: pageBuilder,
barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel,
barrierColor: barrierColor,
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: 'dialog'),
context: overlayContext,
);
settings: routeSettings,
));
}
Future<T> defaultDialog<T>({
... ... @@ -565,7 +599,7 @@ class GetImpl implements GetService {
clipBehavior: clipBehavior,
isDismissible: isDismissible,
modalBarrierColor: barrierColor,
settings: RouteSettings(name: "bottomsheet"),
settings: settings,
enableDrag: enableDrag,
));
}
... ... @@ -742,15 +776,13 @@ class GetImpl implements GetService {
if (instantInit) {
getBar.show();
} else {
_routing.isSnackbar = true;
routing.isSnackbar = true;
SchedulerBinding.instance.addPostFrameCallback((_) {
getBar.show();
});
}
}
ParseRouteTree routeTree;
void addPages(List<GetPage> getPages) {
if (getPages != null) {
if (routeTree == null) routeTree = ParseRouteTree();
... ... @@ -770,6 +802,7 @@ class GetImpl implements GetService {
/// change default config of Get
void config(
{bool enableLog,
LogWriterCallback logWriterCallback,
bool defaultPopGesture,
bool defaultOpaqueRoute,
Duration defaultDurationTransition,
... ... @@ -778,6 +811,9 @@ class GetImpl implements GetService {
if (enableLog != null) {
GetConfig.isLogEnable = enableLog;
}
if (logWriterCallback != null) {
GetConfig.log = logWriterCallback;
}
if (defaultPopGesture != null) {
this.defaultPopGesture = defaultPopGesture;
}
... ... @@ -797,12 +833,6 @@ class GetImpl implements GetService {
}
}
CustomTransition customTransition;
GetMaterialController getxController = GetMaterialController();
Locale locale;
void updateLocale(Locale l) {
locale = l;
forceAppUpdate();
... ... @@ -817,8 +847,6 @@ class GetImpl implements GetService {
(context as Element).visitChildren(rebuild);
}
Map<String, Map<String, String>> translations = {};
void addTranslations(Map<String, Map<String, String>> tr) {
translations.addAll(tr);
}
... ... @@ -846,62 +874,47 @@ class GetImpl implements GetService {
return key;
}
GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
Map<int, GlobalKey<NavigatorState>> _keys = {};
GlobalKey<NavigatorState> nestedKey(int key) {
_keys.putIfAbsent(key, () => GlobalKey<NavigatorState>());
return _keys[key];
keys.putIfAbsent(key, () => GlobalKey<NavigatorState>());
return keys[key];
}
GlobalKey<NavigatorState> global(int k) {
if (k == null) {
return key;
}
if (!_keys.containsKey(k)) {
if (!keys.containsKey(k)) {
throw 'route id not found';
}
return _keys[k];
return keys[k];
}
/// give access to Routing API from GetObserver
Routing get routing => _routing;
RouteSettings get routeSettings => settings;
Routing _routing = Routing();
Map<String, String> parameters = {};
void setRouting(Routing rt) {
_routing = rt;
}
void setSettings(RouteSettings settings) {
settings = settings;
}
/// give current arguments
Object get arguments => _routing.args;
Object get arguments => routing.args;
/// give name from current route
String get currentRoute => _routing.current;
String get currentRoute => routing.current;
/// give name from previous route
String get previousRoute => _routing.previous;
String get previousRoute => routing.previous;
/// check if snackbar is open
bool get isSnackbarOpen => _routing.isSnackbar;
bool get isSnackbarOpen => routing.isSnackbar;
/// check if dialog is open
bool get isDialogOpen => _routing.isDialog;
bool get isDialogOpen => routing.isDialog;
/// check if bottomsheet is open
bool get isBottomSheetOpen => _routing.isBottomSheet;
bool get isBottomSheetOpen => routing.isBottomSheet;
/// check a raw current route
Route<dynamic> get rawRoute => _routing.route;
Route<dynamic> get rawRoute => routing.route;
/// check if popGesture is enable
bool get isPopGestureEnable => defaultPopGesture;
... ... @@ -943,10 +956,3 @@ class GetImpl implements GetService {
/// give access to Immutable MediaQuery.of(context).size.width
double get width => MediaQuery.of(context).size.width;
}
// ignore: non_constant_identifier_names
final Get = GetImpl();
/// It replaces the Flutter Navigator, but needs no context.
/// You can to use navigator.push(YourRoute()) rather Navigator.push(context, YourRoute());
NavigatorState get navigator => Get.key.currentState;
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/routes/get_route.dart';
import 'package:get/src/navigation/routes/get_route.dart';
class GetPageMatch {
GetPageMatch(this.route);
... ...
import 'package:flutter/material.dart';
import 'package:get/src/state/get_state.dart';
import 'package:get/src/state_manager/simple/get_state.dart';
class GetMaterialController extends GetxController {
Key key;
... ...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/src/core/log.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/routes/get_route.dart';
import 'package:get/src/navigation/routes/get_route.dart';
import 'root_controller.dart';
import 'smart_management.dart';
... ... @@ -30,6 +31,7 @@ class GetMaterialApp extends StatelessWidget {
this.darkTheme,
this.themeMode = ThemeMode.system,
this.locale,
this.fallbackLocale,
this.localizationsDelegates,
this.localeListResolutionCallback,
this.localeResolutionCallback,
... ... @@ -50,6 +52,7 @@ class GetMaterialApp extends StatelessWidget {
this.getPages,
this.opaqueRoute,
this.enableLog,
this.logWriterCallback,
this.popGesture,
this.transitionDuration,
this.defaultGlobalState,
... ... @@ -83,6 +86,7 @@ class GetMaterialApp extends StatelessWidget {
final Map<String, Map<String, String>> translationsKeys;
final Translations translations;
final Locale locale;
final Locale fallbackLocale;
final Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates;
final LocaleListResolutionCallback localeListResolutionCallback;
final LocaleResolutionCallback localeResolutionCallback;
... ... @@ -101,6 +105,7 @@ class GetMaterialApp extends StatelessWidget {
final VoidCallback onInit;
final VoidCallback onDispose;
final bool enableLog;
final LogWriterCallback logWriterCallback;
final bool popGesture;
final SmartManagement smartManagement;
final Bindings initialBinding;
... ... @@ -180,9 +185,9 @@ class GetMaterialApp extends StatelessWidget {
onDispose?.call();
},
initState: (i) {
if (locale != null) {
Get.locale = locale;
}
if (locale != null) Get.locale = locale;
if (fallbackLocale != null) Get.fallbackLocale = fallbackLocale;
if (translations != null) {
Get.translations = translations.keys;
... ... @@ -199,6 +204,7 @@ class GetMaterialApp extends StatelessWidget {
Get.config(
enableLog: enableLog ?? GetConfig.isLogEnable,
logWriterCallback: logWriterCallback,
defaultTransition: defaultTransition ?? Get.defaultTransition,
defaultOpaqueRoute: opaqueRoute ?? Get.isOpaqueRouteDefault,
defaultPopGesture: popGesture ?? Get.isPopGestureEnable,
... ... @@ -221,8 +227,8 @@ class GetMaterialApp extends StatelessWidget {
: initialRoutesGenerate,
onUnknownRoute: onUnknownRoute,
navigatorObservers: (navigatorObservers == null
? <NavigatorObserver>[GetObserver(routingCallback)]
: <NavigatorObserver>[GetObserver(routingCallback)]
? <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
: <NavigatorObserver>[GetObserver(routingCallback, Get.routing)]
..addAll(navigatorObservers)),
builder: builder,
title: title ?? '',
... ... @@ -259,7 +265,7 @@ extension Trans on String {
String get tr {
// Returns the key if locale is null.
if (Get.locale?.languageCode == null) return this;
// Checks whether the language code and country code are present, and whether the key is also present.
if (Get.translations.containsKey(
"${Get.locale.languageCode}_${Get.locale.countryCode}") &&
... ... @@ -267,12 +273,27 @@ extension Trans on String {
.containsKey(this)) {
return Get.translations[
"${Get.locale.languageCode}_${Get.locale.countryCode}"][this];
// Checks if there is a callback language in the absence of the specific country, and if it contains that key.
// Checks if there is a callback language in the absence of the specific country, and if it contains that key.
} else if (Get.translations.containsKey(Get.locale.languageCode) &&
Get.translations[Get.locale.languageCode].containsKey(this)) {
return Get.translations[Get.locale.languageCode][this];
// If there is no corresponding language or corresponding key, return the key.
// If there is no corresponding language or corresponding key, return the key.
} else if (Get.fallbackLocale != null) {
if (Get.translations.containsKey(
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}") &&
Get.translations[
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}"]
.containsKey(this)) {
return Get.translations[
"${Get.fallbackLocale.languageCode}_${Get.fallbackLocale.countryCode}"]
[this];
}
if (Get.translations.containsKey(Get.fallbackLocale.languageCode) &&
Get.translations[Get.fallbackLocale.languageCode].containsKey(this)) {
return Get.translations[Get.fallbackLocale.languageCode][this];
}
return this;
} else {
return this;
}
... ...
... ... @@ -2,5 +2,4 @@ enum SmartManagement {
full,
onlyBuilder,
keepFactory,
// none,
}
... ...
... ... @@ -3,7 +3,8 @@ import 'dart:ui' show lerpDouble;
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/src/get_main.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/core/get_main.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/utils.dart';
import 'bindings_interface.dart';
... ... @@ -26,6 +27,7 @@ class GetPageRoute<T> extends PageRoute<T> {
this.barrierColor,
this.binding,
this.bindings,
this.routeName,
this.page,
this.barrierLabel,
this.maintainState = true,
... ... @@ -41,6 +43,8 @@ class GetPageRoute<T> extends PageRoute<T> {
final GetPageBuilder page;
final String routeName;
final CustomTransition customTransition;
final Bindings binding;
... ... @@ -118,8 +122,9 @@ class GetPageRoute<T> extends PageRoute<T> {
element.dependencies();
}
}
GetConfig.currentRoute = settings.name;
return page();
final pageWidget = page();
GetConfig.currentRoute = settings.name ?? routeName;
return pageWidget;
}
static bool isPopGestureInProgress(PageRoute<dynamic> route) {
... ... @@ -197,6 +202,14 @@ class GetPageRoute<T> extends PageRoute<T> {
child: child)
: child);
case Transition.noTransition:
return popGesture ?? Get.defaultPopGesture
? _CupertinoBackGestureDetector<T>(
enabledCallback: () => _isPopGestureEnabled<T>(this),
onStartPopGesture: () => _startPopGesture<T>(this),
child: child)
: child;
case Transition.rightToLeft:
return SlideRightTransition().buildTransitions(
context,
... ... @@ -376,6 +389,15 @@ class GetPageRoute<T> extends PageRoute<T> {
: child);
}
}
@override
void dispose() {
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
WidgetsBinding.instance.addPostFrameCallback((_) => GetInstance()
.removeDependencyByRoute("${settings?.name ?? routeName}"));
}
super.dispose();
}
}
const double _kBackGestureWidth = 20.0;
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/routes/bindings_interface.dart';
import 'package:get/src/navigation/routes/bindings_interface.dart';
import 'custom_transition.dart';
import 'transitions_type.dart';
... ...
import 'package:flutter/widgets.dart';
import 'package:get/route_manager.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/navigation/dialog/dialog_route.dart';
import 'package:get/src/navigation/routes/default_route.dart';
import 'package:get/src/navigation/snackbar/snack_route.dart';
class Routing {
String current;
String previous;
Object args;
String removed;
Route<dynamic> route;
bool isBack;
bool isSnackbar;
bool isBottomSheet;
bool isDialog;
Routing({
this.current = '',
this.previous = '',
this.args,
this.removed = '',
this.route,
this.isBack,
this.isSnackbar,
this.isBottomSheet,
this.isDialog,
});
void update(void fn(Routing value)) {
fn(this);
}
}
class GetObserver extends NavigatorObserver {
final Function(Routing) routing;
GetObserver([this.routing, this._routeSend]);
final Routing _routeSend;
Route<dynamic> route;
bool isBack;
bool isSnackbar;
bool isBottomSheet;
bool isDialog;
String current;
String previous;
Object args;
// String previousArgs;
String removed;
String name(Route<dynamic> route) {
if (route?.settings?.name != null) {
return route?.settings?.name;
} else if (route is GetPageRoute) {
return route.routeName;
} else if (route is GetDialogRoute) {
return route.name;
} else if (route is GetModalBottomSheetRoute) {
return route.name;
} else {
return route?.settings?.name;
}
}
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
bool isGetPageRoute = route is GetPageRoute;
bool isSnackbar = route is SnackRoute;
bool isDialog = route is GetDialogRoute;
bool isBottomSheet = route is GetModalBottomSheetRoute;
String routeName = name(route);
if (isSnackbar) {
GetConfig.log("[GETX] OPEN SNACKBAR $routeName");
} else if (isBottomSheet) {
GetConfig.log("[GETX] OPEN $routeName");
} else if (isDialog) {
GetConfig.log("[GETX] OPEN $routeName");
} else if (isGetPageRoute) {
GetConfig.log("[GETX] GOING TO ROUTE $routeName");
}
GetConfig.currentRoute = routeName;
_routeSend.update((value) {
if (route is PageRoute) value.current = routeName;
value.args = route?.settings?.arguments;
value.route = route;
value.isBack = false;
value.removed = '';
value.previous = '${previousRoute?.settings?.name}';
value.isSnackbar = isSnackbar;
value.isBottomSheet = isBottomSheet;
value.isDialog = isDialog;
});
if (routing != null) routing(_routeSend);
}
@override
void didPop(Route route, Route previousRoute) {
super.didPop(route, previousRoute);
bool isGetPageRoute = route is GetPageRoute;
bool isSnackbar = route is SnackRoute;
bool isDialog = route is GetDialogRoute;
bool isBottomSheet = route is GetModalBottomSheetRoute;
String routeName = name(route);
if (isSnackbar) {
GetConfig.log("[GETX] CLOSE SNACKBAR $routeName");
} else if (isBottomSheet) {
GetConfig.log("[GETX] CLOSE $routeName");
} else if (isDialog) {
GetConfig.log("[GETX] CLOSE $routeName");
} else if (isGetPageRoute) {
GetConfig.log("[GETX] CLOSE TO ROUTE $routeName");
}
GetConfig.currentRoute = routeName;
_routeSend.update((value) {
if (previousRoute is PageRoute)
value.current = '${previousRoute?.settings?.name}';
value.args = route?.settings?.arguments;
value.route = previousRoute;
value.isBack = true;
value.removed = '';
value.previous = '${route?.settings?.name}';
value.isSnackbar = false;
value.isBottomSheet = false;
value.isDialog = false;
});
if (routing != null) routing(_routeSend);
}
@override
void didReplace({Route newRoute, Route oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
GetConfig.log("[GETX] REPLACE ROUTE ${oldRoute?.settings?.name}");
GetConfig.log("[GETX] NEW ROUTE ${newRoute?.settings?.name}");
GetConfig.currentRoute = name(newRoute);
_routeSend.update((value) {
if (newRoute is PageRoute) value.current = '${newRoute?.settings?.name}';
value.args = newRoute?.settings?.arguments;
value.route = newRoute;
value.isBack = false;
value.removed = '';
value.previous = '${oldRoute?.settings?.name}';
value.isSnackbar = false;
value.isBottomSheet = false;
value.isDialog = false;
});
if (routing != null) routing(_routeSend);
}
@override
void didRemove(Route route, Route previousRoute) {
super.didRemove(route, previousRoute);
GetConfig.log("[GETX] REMOVING ROUTE ${route?.settings?.name}");
_routeSend.update((value) {
value.route = previousRoute;
value.isBack = false;
value.removed = '${route?.settings?.name}';
value.previous = '${route?.settings?.name}';
});
if (routing != null) routing(_routeSend);
}
}
... ...
... ... @@ -375,11 +375,12 @@ class _GetBarState<K extends Object> extends State<GetBar>
child: SafeArea(
minimum: widget.snackPosition == SnackPosition.BOTTOM
? EdgeInsets.only(
bottom: (GetUtils.isGreaterThan(
MediaQuery.of(context).viewInsets.bottom,
MediaQuery.of(context).padding.bottom)
? MediaQuery.of(context).viewInsets.bottom
: MediaQuery.of(context).padding.bottom))
// bottom: (GetUtils.isGreaterThan(
// MediaQuery.of(context).viewInsets.bottom,
// MediaQuery.of(context).padding.bottom)
// ? MediaQuery.of(context).viewInsets.bottom
// : MediaQuery.of(context).padding.bottom))
bottom: MediaQuery.of(context).viewInsets.bottom)
: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
bottom: widget.snackPosition == SnackPosition.BOTTOM,
top: widget.snackPosition == SnackPosition.TOP,
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/root/smart_management.dart';
import '../../get_main.dart';
class Routing {
String current;
String previous;
Object args;
String removed;
Route<dynamic> route;
bool isBack;
bool isSnackbar;
bool isBottomSheet;
bool isDialog;
Routing({
this.current,
this.previous,
this.args,
this.removed,
this.route,
this.isBack,
this.isSnackbar,
this.isBottomSheet,
this.isDialog,
});
}
class GetObserver extends NavigatorObserver {
final Function(Routing) routing;
GetObserver([this.routing]);
Route<dynamic> route;
bool isBack;
bool isSnackbar;
bool isBottomSheet;
bool isDialog;
String current;
String previous;
Object args;
// String previousArgs;
String removed;
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
if ('${route?.settings?.name}' == 'snackbar') {
if (GetConfig.isLogEnable)
print("[OPEN SNACKBAR] ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'bottomsheet') {
if (GetConfig.isLogEnable)
print("[OPEN BOTTOMSHEET] ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'dialog') {
if (GetConfig.isLogEnable)
print("[OPEN DIALOG] ${route?.settings?.name}");
} else {
if (GetConfig.isLogEnable)
print("[GOING TO ROUTE] ${route?.settings?.name}");
}
isSnackbar = '${route?.settings?.name}' == 'snackbar';
isDialog = '${route?.settings?.name}' == 'dialog';
isBottomSheet = '${route?.settings?.name}' == 'bottomsheet';
current = '${route?.settings?.name}';
previous = '${previousRoute?.settings?.name}';
args = route?.settings?.arguments;
// previousArgs = previousRoute?.settings?.arguments;
final routeSend = Routing(
removed: null,
isBack: false,
route: route,
current: '${route?.settings?.name}',
previous: '${previousRoute?.settings?.name}',
args: route?.settings?.arguments,
// previousArgs: previousRoute?.settings?.arguments,
isSnackbar: isSnackbar,
isDialog: isDialog,
isBottomSheet: isBottomSheet,
);
if (routing != null) {
routing(routeSend);
}
GetConfig.currentRoute = current;
Get.setRouting(routeSend);
}
@override
void didPop(Route route, Route previousRoute) {
super.didPop(route, previousRoute);
if ('${route?.settings?.name}' == 'snackbar') {
if (GetConfig.isLogEnable)
print("[CLOSE SNACKBAR] ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'bottomsheet') {
if (GetConfig.isLogEnable)
print("[CLOSE BOTTOMSHEET] ${route?.settings?.name}");
} else if ('${route?.settings?.name}' == 'dialog') {
if (GetConfig.isLogEnable)
print("[CLOSE DIALOG] ${route?.settings?.name}");
} else {
if (GetConfig.isLogEnable) print("[BACK ROUTE] ${route?.settings?.name}");
}
if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
GetInstance().removeDependencyByRoute("${route?.settings?.name}");
}
isSnackbar = false;
isDialog = false;
isBottomSheet = false;
current = '${previousRoute?.settings?.name}';
previous = '${route?.settings?.name}';
args = previousRoute?.settings?.arguments;
// previousArgs = route?.settings?.arguments;
final routeSend = Routing(
removed: null,
isBack: true,
route: previousRoute,
current: '${previousRoute?.settings?.name}',
previous: '${route?.settings?.name}',
args: previousRoute?.settings?.arguments,
// previousArgs: route?.settings?.arguments,
isSnackbar: false, //'${route?.settings?.name}' == 'snackbar',
isDialog: false, //'${route?.settings?.name}' == 'dialog',
isBottomSheet: false, //'${route?.settings?.name}' == 'bottomsheet',
);
if (routing != null) {
routing(routeSend);
}
GetConfig.currentRoute = current;
Get.setRouting(routeSend);
}
@override
void didReplace({Route newRoute, Route oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (GetConfig.isLogEnable)
print("[REPLACE ROUTE] ${oldRoute?.settings?.name}");
if (GetConfig.isLogEnable) print("[NEW ROUTE] ${newRoute?.settings?.name}");
if (GetConfig.smartManagement == SmartManagement.full) {
GetInstance().removeDependencyByRoute("${oldRoute?.settings?.name}");
}
isSnackbar = false;
isDialog = false;
isBottomSheet = false;
final routeSend = Routing(
removed: null, // add '${oldRoute?.settings?.name}' or remain null ???
isBack: false,
route: newRoute,
current: '${newRoute?.settings?.name}',
previous: '${oldRoute?.settings?.name}',
args: newRoute?.settings?.arguments,
// previousArgs: newRoute?.settings?.arguments,
isSnackbar: false,
isBottomSheet: false,
isDialog: false,
);
if (routing != null) {
routing(routeSend);
}
GetConfig.currentRoute = current;
Get.setRouting(routeSend);
}
@override
void didRemove(Route route, Route previousRoute) {
super.didRemove(route, previousRoute);
if (GetConfig.isLogEnable)
print("[REMOVING ROUTE] ${route?.settings?.name}");
if (GetConfig.smartManagement == SmartManagement.full) {
GetInstance().removeDependencyByRoute("${route?.settings?.name}");
}
final routeSend = Routing(
isBack: false,
route: previousRoute,
// current: '${previousRoute?.settings?.name}',
current: current,
args: args,
removed: '${route?.settings?.name}',
// args: previousRoute?.settings?.arguments,
isSnackbar: isSnackbar,
isBottomSheet: isBottomSheet,
isDialog: isDialog,
// previousArgs: route?.settings?.arguments,
);
if (routing != null) {
routing(routeSend);
}
GetConfig.currentRoute = current;
Get.setRouting(routeSend);
}
}
import 'package:get/get.dart';
import 'rx_interface.dart';
import 'utils/debouncer.dart';
void ever(RxInterface listener, Function(dynamic) callback,
{bool condition = true}) {
listener.subject.stream.listen((event) {
if (condition) {
callback(event);
}
});
}
void once(RxInterface listener, Function(dynamic) callback,
{bool condition = true}) {
int times = 0;
listener.subject.stream.listen((event) {
if (!condition) return null;
times++;
if (times < 2) {
callback(event);
}
});
}
void interval(RxInterface listener, Function(dynamic) callback,
{Duration time, bool condition = true}) {
bool debounceActive = false;
listener.subject.stream.listen((event) async {
if (debounceActive || !condition) return null;
debounceActive = true;
await Future.delayed(time ?? Duration(seconds: 1));
debounceActive = false;
callback(event);
});
}
void debounce(RxInterface listener, Function(dynamic) callback,
{Duration time}) {
final _debouncer = Debouncer(delay: time ?? Duration(milliseconds: 800));
listener.subject.stream.listen((event) {
_debouncer(() {
callback(event);
});
});
}
import 'dart:async';
import 'package:get/get.dart';
import 'rx_interface.dart';
import 'utils/debouncer.dart';
Worker ever(RxInterface listener, Function(dynamic) callback,
{bool condition = true}) {
StreamSubscription sub = listener.subject.stream.listen((event) {
if (condition) callback(event);
});
Future<void> cancel() {
return sub.cancel();
}
return Worker(cancel, '[ever]');
}
Worker everAll(List<RxInterface> listener, Function(dynamic) callback,
{bool condition = true}) {
List<StreamSubscription> evers = <StreamSubscription>[];
for (var i in listener) {
StreamSubscription sub = i.subject.stream.listen((event) {
if (condition) callback(event);
});
evers.add(sub);
}
Future<void> cancel() {
for (var i in evers) {
i.cancel();
}
return Future.value(() {});
}
return Worker(cancel, '[everAll]');
}
Worker once(RxInterface listener, Function(dynamic) callback,
{bool condition = true}) {
StreamSubscription sub;
int times = 0;
sub = listener.subject.stream.listen((event) {
if (!condition) return null;
times++;
if (times < 2) {
callback(event);
} else {
sub.cancel();
}
});
Future<void> cancel() {
return sub.cancel();
}
return Worker(cancel, '[once]');
}
Worker interval(RxInterface listener, Function(dynamic) callback,
{Duration time, bool condition = true}) {
bool debounceActive = false;
StreamSubscription sub = listener.subject.stream.listen((event) async {
if (debounceActive || !condition) return null;
debounceActive = true;
await Future.delayed(time ?? Duration(seconds: 1));
debounceActive = false;
callback(event);
});
Future<void> cancel() {
return sub.cancel();
}
return Worker(cancel, '[interval]');
}
Worker debounce(RxInterface listener, Function(dynamic) callback,
{Duration time}) {
final _debouncer = Debouncer(delay: time ?? Duration(milliseconds: 800));
StreamSubscription sub = listener.subject.stream.listen((event) {
_debouncer(() {
callback(event);
});
});
Future<void> cancel() {
return sub.cancel();
}
return Worker(cancel, '[debounce]');
}
class Worker {
Worker(this.worker, this.type);
final Future<void> Function() worker;
final String type;
void _message() {
GetConfig.log('[Getx] Worker $type disposed');
}
void dispose() {
worker();
_message();
}
void call() {
worker();
_message();
}
}
... ...
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'rx_impl.dart';
import 'rx_interface.dart';
... ... @@ -34,19 +36,20 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
RxInterface _observer;
T controller;
bool isCreator = false;
StreamSubscription subs;
@override
void initState() {
_observer = Rx();
bool isPrepared = GetInstance().isPrepared<T>();
bool isRegistred = GetInstance().isRegistred<T>();
bool isRegistered = GetInstance().isRegistered<T>();
if (widget.global) {
if (isPrepared) {
if (GetConfig.smartManagement != SmartManagement.keepFactory) {
isCreator = true;
}
controller = GetInstance().find<T>();
} else if (isRegistred) {
} else if (isRegistered) {
controller = GetInstance().find<T>();
isCreator = false;
} else {
... ... @@ -60,10 +63,11 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
controller?.onStart();
}
if (widget.initState != null) widget.initState(this);
if (isCreator && GetConfig.smartManagement == SmartManagement.onlyBuilder) {
if (widget.global &&
GetConfig.smartManagement == SmartManagement.onlyBuilder) {
controller?.onStart();
}
_observer.subject.stream.listen((data) => setState(() {}));
subs = _observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
... ... @@ -85,18 +89,18 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
void dispose() {
if (widget.dispose != null) widget.dispose(this);
if (isCreator || widget.assignId) {
if (widget.autoRemove && GetInstance().isRegistred<T>()) {
if (widget.autoRemove && GetInstance().isRegistered<T>()) {
GetInstance().delete<T>();
}
}
subs.cancel();
_observer.close();
controller = null;
isCreator = null;
super.dispose();
}
Widget get notifyChilds {
Widget get notifyChildren {
final observer = getObs;
getObs = _observer;
final result = widget.builder(controller);
... ... @@ -115,5 +119,5 @@ class GetImplXState<T extends DisposableInterface> extends State<GetX<T>> {
}
@override
Widget build(BuildContext context) => notifyChilds;
Widget build(BuildContext context) => notifyChildren;
}
... ...
... ... @@ -66,16 +66,17 @@ class _RxImpl<T> implements RxInterface<T> {
stream.listen(onData, onError: onError, onDone: onDone);
void bindStream(Stream<T> stream) => stream.listen((va) => value = va);
Stream<R> map<R>(R mapper(T data)) => stream.map(mapper);
}
class RxMap<K, V> extends RxInterface implements Map<K, V> {
class RxMap<K, V> extends RxInterface<Map<K, V>> implements Map<K, V> {
RxMap([Map<K, V> initial]) {
_value = initial;
}
@override
StreamController subject = StreamController<Map<K, V>>.broadcast();
StreamController<Map<K, V>> subject = StreamController<Map<K, V>>.broadcast();
final Map<Stream<Map<K, V>>, StreamSubscription> _subscriptions = {};
Map<K, V> _value;
... ... @@ -247,7 +248,7 @@ class RxMap<K, V> extends RxInterface implements Map<K, V> {
}
/// Create a list similar to `List<T>`
class RxList<E> extends Iterable<E> implements RxInterface<E> {
class RxList<E> extends Iterable<E> implements RxInterface<List<E>> {
RxList([List<E> initial]) {
_list = initial;
}
... ... @@ -265,8 +266,8 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
@override
bool get isNotEmpty => value.isNotEmpty;
StreamController<E> subject = StreamController<E>.broadcast();
Map<Stream<E>, StreamSubscription> _subscriptions = Map();
StreamController<List<E>> subject = StreamController<List<E>>.broadcast();
Map<Stream<List<E>>, StreamSubscription> _subscriptions = Map();
/// Adds [item] only if [condition] resolves to true.
void addIf(condition, E item) {
... ... @@ -282,7 +283,7 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
operator []=(int index, E val) {
_list[index] = val;
subject.add(val);
subject.add(_list);
}
E operator [](int index) {
... ... @@ -291,12 +292,12 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
void add(E item) {
_list.add(item);
subject.add(item);
subject.add(_list);
}
void addAll(Iterable<E> item) {
_list.addAll(item);
subject.add(null);
subject.add(_list);
}
/// Adds only if [item] is not null.
... ... @@ -311,12 +312,12 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
void insert(int index, E item) {
_list.insert(index, item);
subject.add(item);
subject.add(_list);
}
void insertAll(int index, Iterable<E> iterable) {
_list.insertAll(index, iterable);
subject.add(iterable.last);
subject.add(_list);
}
int get length => value.length;
... ... @@ -329,41 +330,41 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
bool remove(Object item) {
bool hasRemoved = _list.remove(item);
if (hasRemoved) {
subject.add(item);
subject.add(_list);
}
return hasRemoved;
}
E removeAt(int index) {
E item = _list.removeAt(index);
subject.add(item);
subject.add(_list);
return item;
}
E removeLast() {
E item = _list.removeLast();
subject.add(item);
subject.add(_list);
return item;
}
void removeRange(int start, int end) {
_list.removeRange(start, end);
subject.add(null);
subject.add(_list);
}
void removeWhere(bool Function(E) test) {
_list.removeWhere(test);
subject.add(null);
subject.add(_list);
}
void clear() {
_list.clear();
subject.add(null);
subject.add(_list);
}
void sort([int compare(E a, E b)]) {
_list.sort();
subject.add(null);
subject.add(_list);
}
close() {
... ... @@ -382,7 +383,7 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
void update(void fn(Iterable<E> value)) {
fn(value);
subject.add(null);
subject.add(_list);
}
/// Replaces all existing items of this list with [items]
... ... @@ -400,7 +401,7 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
String get string => value.toString();
addListener(Stream<E> rxGetx) {
addListener(Stream<List<E>> rxGetx) {
if (_subscriptions.containsKey(rxGetx)) {
return;
}
... ... @@ -412,12 +413,12 @@ class RxList<E> extends Iterable<E> implements RxInterface<E> {
set value(Iterable<E> val) {
if (_list == val) return;
_list = val;
subject.add(null);
subject.add(_list);
}
Stream<E> get stream => subject.stream;
Stream<List<E>> get stream => subject.stream;
StreamSubscription<E> listen(void Function(E) onData,
StreamSubscription<List<E>> listen(void Function(List<E>) onData,
{Function onError, void Function() onDone, bool cancelOnError}) =>
stream.listen(onData, onError: onError, onDone: onDone);
... ...
import 'dart:async';
import 'package:flutter/scheduler.dart';
import 'package:get/src/rx/rx_callbacks.dart';
import 'package:get/src/state_manager/rx/rx_callbacks.dart';
abstract class RxInterface<T> {
RxInterface([T initial]);
/// add listener to stream
addListener(Stream<T> rxGetx);
void addListener(Stream<T> rxGetx);
bool get canUpdate;
/// close stream
close() {
void close() {
subject?.close();
}
... ... @@ -21,6 +21,11 @@ abstract class RxInterface<T> {
StreamSubscription<T> listen(ValueCallback<T> callback);
}
/// Unlike GetxController, which serves to control events on each of its pages,
/// GetxService is not automatically disposed. It is ideal for situations where,
/// once started, that service will remain in memory, such as Auth control for example.
abstract class GetxService extends DisposableInterface {}
abstract class DisposableInterface {
/// Called at the exact moment that the widget is allocated in memory.
/// Do not overwrite this method.
... ...
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/src/rx/rx_interface.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'rx_impl.dart';
Widget obx(Widget Function() builder) {
... ... @@ -24,6 +27,13 @@ class Obxx extends StatelessWidget {
}
}
/// The simplest reactive widget in GetX.
///
/// Just pass your Rx variable in the root scope of the callback to have it
/// automatically registered for changes.
///
/// final _name = "GetX".obs;
/// Obx(() => Text( _name.value )),... ;
class Obx extends StatefulWidget {
final Widget Function() builder;
... ... @@ -33,6 +43,7 @@ class Obx extends StatefulWidget {
class _ObxState extends State<Obx> {
RxInterface _observer;
StreamSubscription subs;
_ObxState() {
_observer = Rx();
... ... @@ -40,12 +51,13 @@ class _ObxState extends State<Obx> {
@override
void initState() {
_observer.subject.stream.listen((data) => setState(() {}));
subs = _observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
@override
void dispose() {
subs.cancel();
_observer.close();
super.dispose();
}
... ... @@ -71,3 +83,59 @@ class _ObxState extends State<Obx> {
@override
Widget build(BuildContext context) => notifyChilds;
}
/// Similar to Obx, but manages a local state.
/// Pass the initial data in constructor.
/// Useful for simple local states, like toggles, visibility, themes,
/// button states, etc.
/// Sample:
/// ObxValue((data) => Switch(
/// value: data.value,
/// onChanged: (flag) => data.value = flag,
/// ),
/// false.obs,
/// ),
// TODO: change T to a proper Rx interfase, that includes the accessor for ::value
class ObxValue<T extends RxInterface> extends StatefulWidget {
final Widget Function(T) builder;
final T data;
const ObxValue(this.builder, this.data, {Key key}) : super(key: key);
_ObxValueState createState() => _ObxValueState();
}
class _ObxValueState extends State<ObxValue> {
RxInterface _observer;
StreamSubscription subs;
_ObxValueState() {
_observer = Rx();
}
@override
void initState() {
subs = _observer.subject.stream.listen((data) => setState(() {}));
super.initState();
}
@override
void dispose() {
subs.cancel();
_observer.close();
super.dispose();
}
Widget get notifyChilds {
final observer = getObs;
getObs = _observer;
// observable is implicity taken from the constructor.
final result = widget.builder(widget.data);
getObs = observer;
return result;
}
@override
Widget build(BuildContext context) => notifyChilds;
}
... ...
import 'dart:collection';
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
import 'package:get/src/root/smart_management.dart';
import 'package:get/src/rx/rx_interface.dart';
import 'package:get/src/navigation/root/smart_management.dart';
import 'package:get/src/state_manager/rx/rx_interface.dart';
import 'package:get/state_manager.dart';
import 'simple_builder.dart';
typedef Disposer = void Function();
class GetxController extends DisposableInterface {
final HashSet<UpdaterBuilder> _updaters = HashSet<UpdaterBuilder>();
final HashSet<StateSetter> _updaters = HashSet<StateSetter>();
final HashMap<String, StateSetter> _updatersIds =
HashMap<String, StateSetter>();
/// Update GetBuilder with update();
void update([List<String> ids, bool condition = true]) {
if (!condition) return;
(ids == null)
? _updaters.forEach((rs) {
rs().updater(() {});
})
: _updaters
.where((element) => ids.contains(element().id))
.forEach((rs) => rs().updater(() {}));
? _updaters.forEach((rs) => rs(() {}))
: ids.forEach((element) {
_updatersIds[element]?.call(() {});
});
}
Disposer addListener(StateSetter listener) {
_updaters.add(listener);
return () => _updaters.remove(listener);
}
// void removeListener(StateSetter listener) {
// _updaters.remove(listener);
// }
Disposer addListenerId(String key, StateSetter listener) {
_updatersIds[key] = listener;
return () => _updatersIds.remove(key);
}
void disposeKey(String key) => _updatersIds.remove(key);
@override
void onInit() async {}
... ... @@ -59,47 +81,46 @@ class GetBuilder<T extends GetxController> extends StatefulWidget {
}
class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
T controller;
UpdaterBuilder real;
GetxController controller;
bool isCreator = false;
final HashSet<Disposer> disposers = HashSet<Disposer>();
Disposer remove;
@override
void initState() {
super.initState();
if (widget.initState != null) widget.initState(this);
if (widget.global) {
final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
final isRegistred = GetInstance().isRegistred<T>(tag: widget.tag);
final isRegistered = GetInstance().isRegistered<T>(tag: widget.tag);
if (isPrepared) {
if (GetConfig.smartManagement != SmartManagement.keepFactory) {
isCreator = true;
}
controller = GetInstance().find<T>(tag: widget.tag);
real = () => Updater(updater: setState, id: widget.id);
controller._updaters.add(real);
} else if (isRegistred) {
} else if (isRegistered) {
controller = GetInstance().find<T>(tag: widget.tag);
isCreator = false;
real = () => Updater(updater: setState, id: widget.id);
controller._updaters.add(real);
} else {
controller = widget.init;
isCreator = true;
real = () => Updater(updater: setState, id: widget.id);
controller._updaters.add(real);
GetInstance().put<T>(controller, tag: widget.tag);
}
} else {
controller = widget.init;
isCreator = true;
real = () => Updater(updater: setState, id: widget.id);
controller._updaters.add(real);
controller?.onStart();
}
if (widget.initState != null) widget.initState(this);
if (isCreator && GetConfig.smartManagement == SmartManagement.onlyBuilder) {
if (widget.global &&
GetConfig.smartManagement == SmartManagement.onlyBuilder) {
controller?.onStart();
}
remove = (widget.id == null)
? controller?.addListener(setState)
: controller?.addListenerId(widget.id, setState);
}
@override
... ... @@ -107,13 +128,18 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
super.dispose();
if (widget.dispose != null) widget.dispose(this);
if (isCreator || widget.assignId) {
if (widget.autoRemove && GetInstance().isRegistred<T>(tag: widget.tag)) {
controller._updaters.remove(real);
if (widget.autoRemove && GetInstance().isRegistered<T>(tag: widget.tag)) {
if (remove != null) remove();
GetInstance().delete<T>(tag: widget.tag);
}
} else {
controller._updaters.remove(real);
if (remove != null) remove();
}
disposers.forEach((element) {
element();
});
}
@override
... ... @@ -131,15 +157,22 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> {
}
@override
Widget build(BuildContext context) {
return widget.builder(controller);
}
Widget build(BuildContext context) => widget.builder(controller);
}
class Updater {
final StateSetter updater;
final String id;
const Updater({this.updater, this.id});
}
/// This is a experimental feature
class Value<T> extends GetxController {
Value([this._value]);
T _value;
T get value {
TaskManager.instance.notify(_updaters);
return _value;
}
typedef UpdaterBuilder = Updater Function();
set value(T newValue) {
if (_value == newValue) return;
_value = newValue;
update();
}
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/instance/get_instance.dart';
abstract class GetWidget<T> extends StatelessWidget {
const GetWidget({Key key}) : super(key: key);
T get controller => GetInstance().find();
abstract class GetView<T> extends StatelessWidget {
const GetView({Key key}) : super(key: key);
T get controller => GetInstance().find<T>();
@override
Widget build(BuildContext context);
}
abstract class GetView<T> extends StatelessWidget {
const GetView({Key key}) : super(key: key);
T get controller => GetInstance().find();
abstract class GetWidget<T> extends StatelessWidget {
GetWidget({Key key}) : super(key: key);
final Set<T> _value = Set<T>();
T get controller {
if (_value.isEmpty) _value.add(GetInstance().find<T>());
return _value.first;
}
@override
Widget build(BuildContext context);
... ...
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:get/src/instance/get_instance.dart';
// import 'package:get/state_manager.dart';
// abstract class GetState<T> extends DisposableInterface {
// GetState(this.initialValue) {
// _state = initialValue;
// }
// final Set<StateSetter> _updaters = Set<StateSetter>();
// @protected
// void update(T value, [bool condition = true]) {
// if (!condition) return;
// _state = value;
// _updaters.forEach((rs) => rs(() {}));
// }
// T _state;
// final T initialValue;
// void addListener(StateSetter value) {
// _updaters.add(value);
// }
// void removeListener(StateSetter value) {
// _updaters.add(value);
// }
// // @protected
// T get state => _state;
// @protected
// void updater(void fn(T value)) {
// fn(_state);
// update(_state);
// }
// }
// class StateBuilder<T extends GetState> extends StatefulWidget {
// final Widget Function(dynamic) builder;
// final bool global;
// final String tag;
// final bool autoRemove;
// final bool assignId;
// final void Function(State state) initState, dispose, didChangeDependencies;
// final void Function(StateBuilder oldWidget, State state) didUpdateWidget;
// final T Function() state;
// const StateBuilder({
// Key key,
// this.state,
// this.global = true,
// @required this.builder,
// this.autoRemove = true,
// this.assignId = false,
// this.initState,
// this.tag,
// this.dispose,
// this.didChangeDependencies,
// this.didUpdateWidget,
// }) : assert(builder != null),
// super(key: key);
// @override
// _StateBuilderState<T> createState() => _StateBuilderState<T>();
// }
// class _StateBuilderState<T extends GetState> extends State<StateBuilder<T>> {
// T controller;
// bool isCreator = false;
// @override
// void initState() {
// super.initState();
// if (widget.initState != null) widget.initState(this);
// if (widget.global) {
// final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag);
// final isRegistred = GetInstance().isRegistred<T>(tag: widget.tag);
// if (isPrepared) {
// isCreator = true;
// } else if (isRegistred) {
// isCreator = false;
// } else {
// isCreator = true;
// }
// if (isCreator) {
// controller?.onStart();
// }
// final instance = GetInstance().putOrFind(widget.state, tag: widget.tag);
// controller = instance;
// controller._updaters.add(setState);
// } else {
// controller = widget.state();
// isCreator = true;
// controller._updaters.add(setState);
// controller?.onStart();
// }
// }
// @override
// void dispose() {
// super.dispose();
// if (widget.dispose != null) widget.dispose(this);
// if (isCreator || widget.assignId) {
// if (widget.autoRemove && GetInstance().isRegistred<T>(tag: widget.tag)) {
// controller._updaters.remove(setState);
// GetInstance().delete<T>(tag: widget.tag);
// }
// } else {
// controller._updaters.remove(setState);
// }
// }
// @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// if (widget.didChangeDependencies != null) {
// widget.didChangeDependencies(this);
// }
// }
// @override
// void didUpdateWidget(StateBuilder oldWidget) {
// super.didUpdateWidget(oldWidget as StateBuilder<T>);
// if (widget.didUpdateWidget != null) widget.didUpdateWidget(oldWidget, this);
// }
// @override
// Widget build(BuildContext context) {
// return widget.builder(controller.state);
// }
// }
... ...
import 'package:flutter/widgets.dart';
import 'package:get/src/rx/rx_obx.dart';
import 'package:get/src/state_manager/rx/rx_obx.dart';
import 'get_state.dart';
class MixinBuilder<T extends GetxController> extends StatelessWidget {
... ...