袁博文

覆盖版本至4.6.5

Signed-off-by: 袁博文 <bwyuan@isoftstone.com>
Showing 71 changed files with 1453 additions and 1516 deletions

Too many changes to show.

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

## [5.0.0-release-candidate-6]
## [4.6.5]
Fix pub dev score
-Fix Snackbar, upgrade to flutter 3.22 @Aniketkhote, improve parse route @korutx, fix popScope @wowbox, improve defaultDialog @leeyi, add support to wasm compilation @Ty, fix typos @CodeWithEmad, fix snackbar cancel @seungsuyoo update GetConnect @DaZealous and @ wheeOs, add bengali language @aratheunseen, fix lint issues: @MuhammamdArslanKhan
## [4.6.4]
Added backward compatibility with flutter 2.
## [5.0.0-release-candidate-5]
## [4.6.3]
Fix SDK constraints
-Fix nested route issues, fixed issues in the latest flutter version
## [5.0.0-release-candidate-4]
-Fix changeThemeMode and RxList
## [5.0.0-release-candidate-3]
-Fix changeTheme
## [5.0.0-release-candidate-2]
This version adds built-in support for animation in Flutter in an easy, clear way, and without having to create a StatefulWidget with controllers and animations. All you need to do is call the name of the animation.
If you want to add a "fadeIn" effect to any widget, simply add .fadeIn() to the end of it.
```dart
Container(
color: Colors.blue,
height: 100,
width: 100,
).fadeIn(),
```
https://user-images.githubusercontent.com/35742643/221383556-075a0b71-1617-4a31-a3c7-1acc68732f59.mp4
Maybe you want to merge two or more animations, just concatenate them at the end of the widget.
```dart
Container(
color: Colors.blue,
height: 100,
width: 100,
).fadeIn().bounce(begin: -0.8, end: 0.3),
```
https://user-images.githubusercontent.com/35742643/221383613-9044c92f-7c6b-48c4-aa79-0a0c20d4068a.mp4
Creating animation sequences in Flutter is one of the most painful things to do with the framework. You need to create tons of AnimationControllers. Well, using GetX 5 you just need to tell your animation that it is sequential. Just like that.
```dart
const FlutterLogo(size: 110)
.bounce(begin: -0.8, end: 0.4)
.fadeIn()
.spin(isSequential: true)
.wobble(isSequential: true, begin: 0, end: 8)
.flip(isSequential: true)
.fadeOut(isSequential: true),
```
Result:
https://user-images.githubusercontent.com/35742643/221393968-20cb2411-516b-44a7-8b85-45090bece532.mp4
## [5.0.0-release-candidate]
Refactor StateManager, RouteManager and InstanceManager from scratch
Fixed Bugs
Added a Scopped DI
Api now uses Navigator 2
Added new RouteOutlet
Added a new futurize method to StateMixin, that tracks updates, errors, and states programatically,
## [4.6.2]
Added compatibility with flutter 3.0
## [4.6.1]
Fix GetConnect on Flutter web
## [4.6.0]
Add useInheritedMediaQuery to GetMaterialApp and GetCupertinoApp (@davidhole)
Add Circular reveal Transition (@parmarravi)
Add request to failed response (@heftekharm)
... ... @@ -84,12 +25,11 @@ Add proxy setting support to GetConnect (@jtans)
Fix markAsDirty used on permanent controllers (@zenalex)
Update Korean readme (@dumbokim)
## [4.5.1]
## [4.5.1]
Fix Snackbar when it have action and icon the same time
## [4.5.0] - Big Update
To have a page-agnostic snackbar, we used OverlayRoute to display a partial route.
However this had several problems:
... ... @@ -139,23 +79,23 @@ Breaking and Depreciation:
GetBar is now deprecated, use GetSnackbar instead.
dismissDirection now gets a DismissDirection, making the Snackbar more customizable.
## [4.3.8]
- Fix nav2 toNamed remove the route
## [4.3.7]
## [4.3.8]
- Fix nav2 toNamed remove the route
## [4.3.7]
- Fix wrong currentRoute when a route is removed
- Remove take that limits the router outlet depth (@steven-spiel)
## [4.3.6]
## [4.3.6]
- Fix error with autodispose of additional dependencies beyond GetxController
- Added ability to add your own delegate to RouterOutlet (@steven-spiel)
- Added listenAndPump to Rx to give Rx the same behavior as BehaviorSubject (@steven-spiel)
## [4.3.5]
## [4.3.5]
- Fix GetConnect timeout (@jasonlaw)
- Improve Vietnamese docs (@hp1909)
- Refactor placeholder name route to unnamed routes (@roipeker).
... ... @@ -163,51 +103,42 @@ dismissDirection now gets a DismissDirection, making the Snackbar more customiza
- Fix: Wrong nameRoute after a route is removed
- Added assert to prevent the user from starting a route name without slash.
## [4.3.4]
## [4.3.4]
- Improve docs
## [4.3.3]
## [4.3.3]
- Fix Get.reset
## [4.3.2]
## [4.3.2]
- Fix nullable on internacionalization (@jmguillens)
- Fix nullable on Rx.stream (@steven-spiel)
## [4.3.1]
## [4.3.1]
- Fix controller is not removed when keyboard is open.
- Improved: Safe removal and insertion of controllers.
## [4.3.0]
## [4.3.0]
- Added GetResponsiveWidget (@ahmednfwela)
- Added `Get.replace()` (@jwelmac)
- Added Improve korean doc (@sejun2)
- Fix multiple middlewares redirect (@liasica)
- Added gestureWidth and showCupertinoParallax to GetPage to customize cupertino transitions
## [4.2.5]
## [4.2.5]
- Added anchorRoute and filterPages to GetRouterOutlet (@ahmednfwela)
- Added scrollBehavior and scaffoldMessengerKey to GetMaterialapp(@ejabu and @alionour)
- Fix error when child on MaterialApp is null (@ahmednfwela)
- Fix Korean docs (@rws08)
- Fix error with onClose called before routeTransition on Get.offNamed
## [4.2.4]
## [4.2.4]
- Fix Get.offAll removing GetxServices from memory
## [4.2.3]
## [4.2.3]
- Fix back button on navigator 2
- Added parameters and arguments to Get.rootDelegate
## [4.2.1]
- Added parameters and arguments to Get.rootDelegate
## [4.2.1]
- Remove [] from docs to try fix pub score
## [4.2.0] - Big update
... ... @@ -218,102 +149,101 @@ Changes in this version:
- Fix: Navigating to the same page with Get.offNamed does not delete the controller from that page using Get.lazyPut.
- Fix Readme GetMiddleware typos
by @nivisi
- Fix Readme GetMiddleware typos
by @nivisi
- Fix url replace error
by @KevinZhang19870314
by @KevinZhang19870314
- Changed response default encoding from latin1 to utf8
by @heftekharm
- Changed response default encoding from latin1 to utf8
by @heftekharm
- Add Duration in ExtensionBottomSheet
by @chanonpingpong
by @chanonpingpong
- Added compatibility with dart-lang/mockito
by @lifez
by @lifez
- Added extensions methods to convert value in percent value
by @kauemurakami
- Added extensions methods to convert value in percent value
by @kauemurakami
- Set darkTheme equal theme when darkTheme is null
by @eduardoFlorence
- Set darkTheme equal theme when darkTheme is null
by @eduardoFlorence
- Add padding to 'defaultDialog'
by @KevinZhang19870314
- Add padding to 'defaultDialog'
by @KevinZhang19870314
- GraphQLResponse inherit Response info
by @jasonlaw
- GraphQLResponse inherit Response info
by @jasonlaw
- Fix Redundant concatenating base url
by @jasonlaw
- Fix Redundant concatenating base url
by @jasonlaw
- Add content type and length into the headers when the content type is 'application/x-www-form-urlencoded'
by @calvingit
by @calvingit
- Make withCredentials configurable
by @jasonlaw
- Make withCredentials configurable
by @jasonlaw
- Fix flutter 2.0 error
by @yunchiri
by @yunchiri
- Allow deleting all registered instances
by @lemps
by @lemps
- Refactor/rx interface notify children
@by kranfix
- Refactor/rx interface notify children
@by kranfix
- Fixed parameter parsing and middleware sorting
by @ahmednfwela
- Fixed parameter parsing and middleware sorting
by @ahmednfwela
- Improvements to router outlet
by @ahmednfwela
- Improvements to router outlet
by @ahmednfwela
- Minor improvements and bug fixes
by @ahmednfwela
- Minor improvements and bug fixes
by @ahmednfwela
- Adding route guards and improving navigation
by @ahmednfwela
- Adding route guards and improving navigation
by @ahmednfwela
- Fix RxInterface.proxy losing its previous value on exception
by @WillowWisp
by @WillowWisp
- Added dispose() for bottomSheet.
by @furkankurt
by @furkankurt
- Added Pull request template
by @unacorbatanegra
- Added Pull request template
by @unacorbatanegra
- Fix and update documentation:
@Farid566,
@galaxykhh,
@arslee07,
@GoStaRoff,
@BondarenkoArtur,
@denisrudnei,
@Charly6596,
@nateshmbhat,
@hrithikrtiwari,
@Undeadlol1,
@rws08,
@inuyashaaa,
@broccolism,
@aadarshadhakalg,
@ZeroMinJeon
## [4.1.4]
@Farid566,
@galaxykhh,
@arslee07,
@GoStaRoff,
@BondarenkoArtur,
@denisrudnei,
@Charly6596,
@nateshmbhat,
@hrithikrtiwari,
@Undeadlol1,
@rws08,
@inuyashaaa,
@broccolism,
@aadarshadhakalg,
@ZeroMinJeon
## [4.1.4]
- Adjust operator + and - to RxInt (@eduardoflorence)
- Fix dark theme (@eduardoflorence)
- Fix form-urlencoded on GetConnect (@aramayyes)
## [4.1.3]
## [4.1.3]
- Fix "Error: A value of type 'Locale?' can't be returned from a function"on flutter web (@nickwri)
- Fix plural translations to expressions >1 (@WolfVic)
## [4.1.2]
## [4.1.2]
- Fix warning ˜can add data to a closed stream˜ when GetBuilder and Obx are nested
- Fix get_connect decoder can not be null (@Goddchen)
- Migrate example code (@3lB4rt0)
... ... @@ -324,30 +254,25 @@ Changes in this version:
- Fix controller is removed when navigate to same page (@eduardoflorence)
- Fix missing reload() and reloadAll() to Get extensions (@lkloon123)
## [4.1.1]
## [4.1.1]
- Remove mandatory initialValue to nullables types
## [4.1.0]
## [4.1.0]
- Added Rxn to non nullables reactives types
## [4.0.3]
## [4.0.3]
- Added new linter rules to improve score
## [4.0.2]
## [4.0.2]
- Removed "!" of if else conditions until the null-safety of the dart is consistent for using it.
## [4.0.1]
## [4.0.1]
- Fix changelog
## [4.0.0]
## [4.0.0]
- Added append function to StateMixin. Now is possible track loading, success and error handle of your application with ONE LINE OF CODE. Ex: append(()=> api.getUser);
- Migrate to null-safety
- Migrate to null-safety
- Added ScrollMixin to controllers
- Added loadingMore status to RxStatus
- Fix content-type qual null (@katekko)
... ... @@ -365,8 +290,7 @@ You can also use custom Rxn types with null-safety:
`RxInt` == not nullable
`RxnInt` == nullable.
## [3.25.6]
## [3.25.6]
- Added documentation in French (@kamazoun)
- Fix logs messages (@damphat)
- Fix plural to zero on internacionalization (@RafaRuiz)
... ... @@ -374,39 +298,33 @@ You can also use custom Rxn types with null-safety:
- Fix typos on readme (@bashleigh)
- Fix group updates to GetBuilder
## [3.25.5]
## [3.25.5]
- Fix Get.isDialogOpen when two or more open dialogs are closed
## [3.25.4]
## [3.25.4]
- Added logs and tests to unknownRoute
## [3.25.3]
## [3.25.3]
- Fix bindStream error 'Object.noSuchMethod'.
## [3.25.2]
## [3.25.2]
- Improved Workers system to accept a list of works
## [3.25.1]
## [3.25.1]
- Improved the log system to display the tag used in the controller that was created.
## [3.25.0] - Big update
- Added [reload] and [reloadAll] methods to reload your Controller to original values
- Added [FullLifeCycleController] - A GetxController capable of observing all the life cycles of your application. FullLifeCycleController has the life cycles:
- onInit: called when the controller enters the application's memory
- onReady: called after onInit, when build method from widget relationed to controller is done.
- onClose: called when controller is deleted from memory.
- onPaused: called when the application is not currently visible to the user, and running in the background.
- onInactive: called when the application is in an inactive state and is not receiving user input, when the user receives a call, for example
- onResumed: The application is now visible and in the foreground
- onDetached: The application is still hosted on a flutter engine but is detached from any host views.
- didChangeMetrics: called when the window size is changed
- Added SuperController, a complete life circle controller with StateMixin
* onInit: called when the controller enters the application's memory
* onReady: called after onInit, when build method from widget relationed to controller is done.
* onClose: called when controller is deleted from memory.
* onPaused: called when the application is not currently visible to the user, and running in the background.
* onInactive: called when the application is in an inactive state and is not receiving user input, when the user receives a call, for example
* onResumed: The application is now visible and in the foreground
* onDetached: The application is still hosted on a flutter engine but is detached from any host views.
* didChangeMetrics: called when the window size is changed
- Added SuperController, a complete life circle controller with StateMixin
- Improve Iterable Rx Api. Now, you can to use dart List, Map and Set as reactive, like: List<String> names = <String>['juan', 'pedro', 'maria'].obs;
- Added assign and assignAll extensions to default dart List
- Added parameters options from Get.toNamed, Get.offNamed, and Get.offAllNamed (@enghitalo)
... ... @@ -420,7 +338,7 @@ You can also use custom Rxn types with null-safety:
- Added Get.parameter access to Middleware (@eduardoflorence)
- Fix RxBool typo (@emanuelmutschlechner)
- Added Filter to GetBuilder
- Added debouce to GetBuilder update
- Added debouce to GetBuilder update
- Added ability to insert an Enum, class, or type of an object as a GetBuilder's Id
- Improve upload time from GetConnect
- Create minified version to DartPad(@roipeker)
... ... @@ -428,11 +346,11 @@ You can also use custom Rxn types with null-safety:
- Added more status codes to GetConnect (@romavic)
- Fix and improve docs: @unacorbatanegra, @lsm, @nivisi, @ThinkDigitalSoftware, @martwozniak, @UsamaElgendy, @@DominusKelvin, @jintak0401, @goondeal
## [3.24.0]
## [3.24.0]
- GetWidget has been completely redesigned.
Throughout its lifetime, GetWidget has always been mentioned in the documentation as "something you shouldn't use unless you're sure you need it", and it had a very small use case. A short time ago we realized that it could have some unexpected behaviors, when compared to GetView, so we decided to rebuild it from scratch, creating a really useful widget for the ecosystem.
Objectively, GetWidget is now a Widget that caches the controller and protects children from their parents' reconstructions. This means that if you have a ListView or gridview, you can add items to it without the child (being a GetWidget) being rebuilt. The api is now more concise, as you can use Get.put / Get.lazyput for global dependencies, and Get.create with GetWidget for ephemeral dependencies, or when you need several identical controllers for the same widget, eliminating the need for tags for most cases.
Throughout its lifetime, GetWidget has always been mentioned in the documentation as "something you shouldn't use unless you're sure you need it", and it had a very small use case. A short time ago we realized that it could have some unexpected behaviors, when compared to GetView, so we decided to rebuild it from scratch, creating a really useful widget for the ecosystem.
Objectively, GetWidget is now a Widget that caches the controller and protects children from their parents' reconstructions. This means that if you have a ListView or gridview, you can add items to it without the child (being a GetWidget) being rebuilt. The api is now more concise, as you can use Get.put / Get.lazyput for global dependencies, and Get.create with GetWidget for ephemeral dependencies, or when you need several identical controllers for the same widget, eliminating the need for tags for most cases.
- Workers now have error handlers, so if an error occurs in your stream, you can recover it from your workers.
... ... @@ -441,19 +359,19 @@ You can also use custom Rxn types with null-safety:
- [Patch] method was added in GetConnect.
- Native methods for RxString (trim, contains, startWith, etc.) have been added.
- Standard constructors for RxList and RxMap have been added (RxList.generate, RxList.from, Map.of, Map.from, etc).
- Added "onEmpty" status in StateMixin (@alizera)
- Added query and mutation methods of graphql for getconnect.
- Added body string for content-type application/x-www-form-urlencoded on GetConnect (@eduardoflorence)
## [3.23.1]
- Fix allowSelfSigned on Flutter web
## [3.23.0]
- Add GetResponsive (@SchabanBo)
- Update tests, fix predicate for offNamedUntil (@vbuberen)
- Added Urdu Version for Pakistani Developers (@UsamaSarwar)
... ... @@ -468,19 +386,17 @@ You can also use custom Rxn types with null-safety:
- Added Indonesian version to Indonesian Developers (@pratamatama)
## [3.22.2]
- Fix overlayEntries is null on Master/Dev branch of Flutter
## [3.22.1]
- Improve: auto jsonDecode occurs only if response.header.contentType is "application/json"
- Improve and fix requests types (@eduardoflorence)
- Fix HeaderValue variables with same name (@haidang93)
## [3.22.0]
- Added: more multipart options. Now you can send as multipart:
## [3.22.0]
- Added: more multipart options. Now you can send as multipart:
File:
'file':MultipartFile(File('./images/avatar.png'), filename: 'avatar.png'),
... ... @@ -493,22 +409,19 @@ Or bytes (Flutter web work only with bytes):
- Added: Upload Progress to MultipartRequest
- Added support to List<MultipartFile> (@jasonlaw)
## [3.21.3]
## [3.21.3]
- Improve multipart file and defaultDecoder on GetConnect
## [3.21.2]
## [3.21.2]
- Fix GetConnect.request returning a PUT request
## [3.21.1]
## [3.21.1]
- Allow null body to POST method on GetConnect
## [3.21.0] - Big update
- This update attaches two nice features developed by (@SchabanBo): _GetPage Children_ And _GetMiddleware_
In previous versions, to create child pages, you should do something like:
- This update attaches two nice features developed by (@SchabanBo): *GetPage Children* And *GetMiddleware*
In previous versions, to create child pages, you should do something like:
```dart
GetPage(
... ... @@ -527,12 +440,10 @@ GetPage(
binding: ElectronicsBinding(),
),
```
Although the feature works well, it could be improved in several ways:
1- If you had many pages, the page file could become huge and difficult to read. Besides, it was difficult to know which page was the daughter of which module.
2- It was not possible to delegate the function of naming routes to a subroutine file.
With this update, it is possible to create a declarative structure, very similar to the Flutter widget tree for your route, which might look like this:
```dart
GetPage(
name: '/home',
... ... @@ -551,14 +462,13 @@ GetPage(
),
],
),
],
],
);
```
Thus, when accessing the url: '/home/products/electronics'
Or use Get.toNamed('/home/products/electronics') it will go directly to the page [ElectronicsView], because the child pages, automatically inherit the name of the ancestral page, so _with any small change on any father in the tree all children will be updated._ If you change [/products] to [/accessories], you don't nesse update on all child links.
Or use Get.toNamed('/home/products/electronics') it will go directly to the page [ElectronicsView], because the child pages, automatically inherit the name of the ancestral page, so _with any small change on any father in the tree all children will be updated._ If you change [/products] to [/accessories], you don't nesse update on all child links.
However, the most powerful feature of this version is _GetMiddlewares_.
However, the most powerful feature of this version is *GetMiddlewares*.
The GetPage has now new property that takes a list of GetMiddleWare than can perform actions and run them in the specific order.
### Priority
... ... @@ -573,7 +483,6 @@ final middlewares = [
GetMiddleware(priority: -8),
];
```
those middlewares will be run in this order **-8 => 2 => 4 => 5**
### Redirect
... ... @@ -634,66 +543,58 @@ This function will be called right after the GetPage.page function is called and
This function will be called right after disposing all the related objects (Controllers, views, ...) of the page.
## [3.20.1]
- Fix wrong reference with unnamed routes and added more tests
## [3.20.1]
* Fix wrong reference with unnamed routes and added more tests
## [3.20.0] - Big update
- Added GetConnect.
* GetConnect is an easy way to communicate from your back to your front. With it you can:
* Communicate through websockets
* Send messages and events via websockets.
* Listen to messages and events via websockets.
* Make http requests (GET, PUT, POST, DELETE).
* Add request modifiers (like attaching a token to each request made).
* Add answer modifiers (how to change a value field whenever the answer arrives)
* Add an authenticator, if the answer is 401, you can configure the renewal of your JWT, for example, and then it will again make the http request.
* Set the number of attempts for the authenticator
* Define a baseUrl for all requests
* Define a standard encoder for your Model.
* Note1: You will never need to use jsonEncoder. It will always be called automatically with each request. If you define an encoder for your model, it will return the instance of your model class ALREADY FILLED with server data.
* Note2: all requests are safety, you do not need to insert try / catch in requests. It will always return a response. In case of an error code, Response.hasError will return true. The error code will always be returned, unless the error was a connection error, which will be returned Response.hasError, but with error code null.
* These are relatively new features, and also inserted in separate containers. You don't have to use it if you don't want to. As it is relatively new, some functions, such as specific http methods, may be missing.
- Translation to Korean (@rws08)
- Fix Overlays state (@eduardoflorence)
- Update chinese docs (@jonahzheng)
- Added context.isDarkMode to context extensions
* Added GetConnect.
- GetConnect is an easy way to communicate from your back to your front. With it you can:
- Communicate through websockets
- Send messages and events via websockets.
- Listen to messages and events via websockets.
- Make http requests (GET, PUT, POST, DELETE).
- Add request modifiers (like attaching a token to each request made).
- Add answer modifiers (how to change a value field whenever the answer arrives)
- Add an authenticator, if the answer is 401, you can configure the renewal of your JWT, for example, and then it will again make the http request.
- Set the number of attempts for the authenticator
- Define a baseUrl for all requests
- Define a standard encoder for your Model.
- Note1: You will never need to use jsonEncoder. It will always be called automatically with each request. If you define an encoder for your model, it will return the instance of your model class ALREADY FILLED with server data.
- Note2: all requests are safety, you do not need to insert try / catch in requests. It will always return a response. In case of an error code, Response.hasError will return true. The error code will always be returned, unless the error was a connection error, which will be returned Response.hasError, but with error code null.
- These are relatively new features, and also inserted in separate containers. You don't have to use it if you don't want to. As it is relatively new, some functions, such as specific http methods, may be missing.
* Translation to Korean (@rws08)
* Fix Overlays state (@eduardoflorence)
* Update chinese docs (@jonahzheng)
* Added context.isDarkMode to context extensions
## [3.17.1]
- Allow list.assignAll, map.assignAll and set.assignAll operate with null values
## [3.17.0]
- Added GetCupertinoApp
- Added initial suport to navigator 2.0
- Added initial suport to navigator 2.0
## [3.16.2]
- Clean RxList, RxMap and RxSet implementation
- Now when declaring an `RxList()`, it will be started empty. If you want to start a null RxList, you must use `RxList(null)`.
Improved GetStream to receive the same parameters as the StreamController, such as `onListen`, `onPause`, `onResume` and `onCancel`.
Improved GetStream to receive the same parameters as the StreamController, such as `onListen`, `onPause`, `onResume` and `onCancel`.
- Improve docs
## [3.16.1]
- Fix compilation error on master
## [3.16.0]
- Documentation translated into Russian language. (@Renat Fakhrutdinov, @Doaxan and @BatttA)
- Added error message callback for StateMixin (@eduardoflorence)
- Fix incorrect Get.reference when pop route (@4mb1t)
- Fix incorrect Get.reference when pop route (@4mb1t)
- Added Uppercase/Capital letter on GetUtils (@AleFachini)
- Redraw the Streams api to use GetStream instead of StreamControllers. Why this change?
Dart provides a Streams API that is really rich. However, asynchronous streams add extra latency to ensure that events are delivered in the exact order.
It is not yet known whether this latency has any performance impact in mobile applications, and probably not, however, as GetX is also a server-side framework, we need to have the lowest latency at all, since our base is shared.
Dart also has a Synchronous Streams api that has very low latency, however, it is not suitable for use in state management for two reasons:
1- Synchronous Streams can only have one listen (see the issue opened by Hixie on dart lang for reference: https://github.com/dart-lang/sdk/issues/22240).
This means that we cannot use this api for more than one listener, which is the basis of global state management, where we aim to change the state of more than one location. You can test this with this simple snippet:
- Redraw the Streams api to use GetStream instead of StreamControllers. Why this change?
Dart provides a Streams API that is really rich. However, asynchronous streams add extra latency to ensure that events are delivered in the exact order.
It is not yet known whether this latency has any performance impact in mobile applications, and probably not, however, as GetX is also a server-side framework, we need to have the lowest latency at all, since our base is shared.
Dart also has a Synchronous Streams api that has very low latency, however, it is not suitable for use in state management for two reasons:
1- Synchronous Streams can only have one listen (see the issue opened by Hixie on dart lang for reference: https://github.com/dart-lang/sdk/issues/22240).
This means that we cannot use this api for more than one listener, which is the basis of global state management, where we aim to change the state of more than one location. You can test this with this simple snippet:
```dart
void main() {
... ... @@ -714,7 +615,6 @@ void main() {
print("test8");
}
```
2- Even with a single listener, the dart's Synchronous Streams api cannot deliver events in the exact order. We plan to work on a PR in the future at dart-lang to address this. So if we remove the line above that causes the exception, we will have the following output in the log:
```dart
... ... @@ -745,11 +645,9 @@ test8
test5
```
As we can see, test 4 skips to test 6, which skips to test 8, which skips to test 5. Note that test 7 didn't even appear in the log.
However, if we work with GetStream, everything works as expected:
```dart
void main() {
var controller = GetStream();
... ... @@ -792,15 +690,15 @@ In short: asynchronous streams from dart work perfectly, but add a latency that
Synchronous dart streams have unexpected behaviors, cannot have more than 1 listener and do not deliver events in the correct order, which completely prevents their use in mobile state managements, since you run the risk of displaying data on the wrong screen, since the last event will not always be the last event entered by the sink.
The 9000% figures are real, however, they refer to the gross performance between Streams and GetStreams. This does not mean that this number will impact your applications, because you are unlikely to use all of that power.
## [3.15.0] - Big update
## [3.15.0] - Big update
- **Improve Performance**: We made modifications to make GetBuilder even faster. We have improved the structure behind it so that listeners are notified faster. Perhaps in version 4.0 everything will be based on this new structure, but maintaining the power and compatibility with streams. If you want to know how much Getx is faster than pure streams or ChangeNotifier (even after the last update using LinkedList), you can create run the repository tests at: (https://github.com/jonataslaw/getx/blob/master/test/benchmarks/benckmark_test.dart)
- **Added StateMixin**
StateMixin allows you to change the state of the controller, and display a loading, an error message, or a widget you want with 0 boilerplate. This makes things like API/Rest communication or websocket absurdly simple, and it's a real revolution in how state management has behaved so far.
You no longer need to have a ternary in your code, and you don't need a widget like FutureBuilder, StreamBuilder or even Obx/GetBuilder to encompass your Visibility. This will change with the way you manage the state of your controllers, decrease your boilerplate absurdly, and give you more security in your code.
StateMixin allows you to change the state of the controller, and display a loading, an error message, or a widget you want with 0 boilerplate. This makes things like API/Rest communication or websocket absurdly simple, and it's a real revolution in how state management has behaved so far.
You no longer need to have a ternary in your code, and you don't need a widget like FutureBuilder, StreamBuilder or even Obx/GetBuilder to encompass your Visibility. This will change with the way you manage the state of your controllers, decrease your boilerplate absurdly, and give you more security in your code.
- **Added GetNotifier**
GetNotifier is a super and powerful ValueNotifier, which in addition to having the life cycle of the controllers, is extremely fast, and can manage a single state, as a simplified immutable state management solution.
In theory, the only difference between it and GetxController is the possibility of setting an initial value in the constructor's super (exactly as ValueNotifier does). If the initial value is null, use GetxController. If you need a starting value, GetNotifier can be more useful and have less boilerplate, but both serve the same purpose: to decouple your visualization layer from your presentation logic.
GetNotifier is a super and powerful ValueNotifier, which in addition to having the life cycle of the controllers, is extremely fast, and can manage a single state, as a simplified immutable state management solution.
In theory, the only difference between it and GetxController is the possibility of setting an initial value in the constructor's super (exactly as ValueNotifier does). If the initial value is null, use GetxController. If you need a starting value, GetNotifier can be more useful and have less boilerplate, but both serve the same purpose: to decouple your visualization layer from your presentation logic.
- Other Fixes and improvements:
- Fixed GetxController is closed twice when smartManagement.full is turn on
- Fixed phone number validation
... ... @@ -811,19 +709,15 @@ The 9000% figures are real, however, they refer to the gross performance between
- Improve code structure with less duplicate code: (@kranfix)
- Fix named route erroring when route does not exist (@FiercestT)
## [3.13.2]
## [3.13.2]
- Reunification of the package.
During the 2 week period, we try to keep this package as a compilation of smaller packages. We were successful in separating, getx is well decoupled and it was only necessary to send the internal folders as packages to pub.dev, however, it became very complicated to contribute to the package. This is because it was necessary to clone the repository, replace all pubspec packages with local paths, and after modification, return the original paths to do the PR. With that, the frequency of updates, which was about 4 to 5 days, became almost 2 weeks, and this is not legal for a community as active as Getx, which uses this package precisely in addition to being modern and performance, be constantly improving. This led contributors to the conclusion that getx works best together.
Additional packages will continue to be maintained, and will have the same base as the main package, however, development will take place in the full and main package, and as the addition of new features or bug fixes arrives, we will migrate to the individual packages . Getx reached the mark of 50 contributors today, more than 1500 likes in the pub, and will continue to make development easy.
## [3.13.1]
- Remove spaces whitespaces from dart files
-
During the 2 week period, we try to keep this package as a compilation of smaller packages. We were successful in separating, getx is well decoupled and it was only necessary to send the internal folders as packages to pub.dev, however, it became very complicated to contribute to the package. This is because it was necessary to clone the repository, replace all pubspec packages with local paths, and after modification, return the original paths to do the PR. With that, the frequency of updates, which was about 4 to 5 days, became almost 2 weeks, and this is not legal for a community as active as Getx, which uses this package precisely in addition to being modern and performance, be constantly improving. This led contributors to the conclusion that getx works best together.
Additional packages will continue to be maintained, and will have the same base as the main package, however, development will take place in the full and main package, and as the addition of new features or bug fixes arrives, we will migrate to the individual packages . Getx reached the mark of 50 contributors today, more than 1500 likes in the pub, and will continue to make development easy.
## [3.13.1]
- Remove spaces whitespaces from dart files
-
## [3.13.0]
- Fix typos on code and docs (@wbemanuel and @Goddchen)
- Improve: typedef to GetBuilder and Getx widgets
- Improve behaviour of null route on lastest flutter version (@FiercestT)
... ... @@ -831,34 +725,30 @@ The 9000% figures are real, however, they refer to the gross performance between
- Fix onClose called twice when GetBuilder is used
- Fix default customTransitions, and defaultDuration be ignored on unnamedRoutes
- Transition.native use default Flutter transitions
- Added Get.testMode to use contextless elements on unit tests
- Added Get.appUpdate and improve Get.forceAppUpdate
## [3.12.1]
- Remove spaces whitespaces from dart files
## [3.12.0]
- Added BottomSheet Duration && Export SingleGetTickerProvider (@unacorbatanegra)
- Improve docs from dependencies management (@ngxingyu)
- Fix unknownRoute with null Custom Transition (@marcosfons)
- Optimize capitalize method (@zl910627)
- Added Chinese documentation (@idootop)
- Added TextDirection property on GetMaterialApp to improve RTL layout (@justkawal)
- Remove unnecessary files on git (@nipodemos)
- Fix tags on Get.create() and GetWidget() (@roipeker)
- Update mockito dependency on getTests
- Added Get.testMode to use contextless elements on unit tests
- Added Get.appUpdate and improve Get.forceAppUpdate
## [3.12.1]
- Remove spaces whitespaces from dart files
## [3.12.0]
- Added BottomSheet Duration && Export SingleGetTickerProvider (@unacorbatanegra)
- Improve docs from dependencies management (@ngxingyu)
- Fix unknownRoute with null Custom Transition (@marcosfons)
- Optimize capitalize method (@zl910627)
- Added Chinese documentation (@idootop)
- Added TextDirection property on GetMaterialApp to improve RTL layout (@justkawal)
- Remove unnecessary files on git (@nipodemos)
- Fix tags on Get.create() and GetWidget() (@roipeker)
- Update mockito dependency on getTests
- Added GetStatelessWidget, a StatelessWidget base to GetWidget with lifecycle control of controllers. Note: It's a base class, you don't need change to use it or change your GetView, GetWidget StatelessWidget to It.
## [3.11.1]
- Fix docs
## [3.11.0]
- Refactor structure from scratch to split GetX completely into separate packages. When using the main package (get) you will have everything working perfectly together. However, if you only want one of the resources, you can use the packages separately.
- Improve Rx types
- Refactor structure from scratch to split GetX completely into separate packages. When using the main package (get) you will have everything working perfectly together. However, if you only want one of the resources, you can use the packages separately.
- Improve Rx types
- Added RTL support
- Added GetTests, a set of tools to help you create unit tests using Getx
- RAM consumption improved by dividing resources into smaller components, preventing related classes that are unnecessary from being loaded
... ... @@ -881,17 +771,13 @@ The 9000% figures are real, however, they refer to the gross performance between
- Improve readme example (@dafinoer)
## [3.10.2]
- Fixed the use of tags with lazyPut and added Ability to overwrite "tag" in GetView and GetWidget.
## [3.10.1]
- Fix analyzer
## [3.10.0]
Getx 3.10 released with CLI and Get Server.
- Added: analyser + effective dart (@Grohden)
- Added TextStyle to generalDialog title and message (@roipeker)
- renamed and added defaults transition duration and types in "GetInterface" (@roipeker)
... ... @@ -902,7 +788,7 @@ Getx 3.10 released with CLI and Get Server.
- Added Curve property to routes (@roipeker)
- Improve docs, code cleanup, new GetStateUpdaterMixin and GetStateUpdate in favour of StateSetter on GetxController, GetBuilder, SimpleBuilder. (@roipeker)
- Added RxBool.toggle() as an easy shortcut for switching true/false values. (@roipeker)
- Added \_RxImp.nil() to easily set the value to null (@roipeker)
- Added _RxImp.nil() to easily set the value to null (@roipeker)
- Added missing docs to Rx classes. (@roipeker)
- Added Get.delete(force:false) to Get extensions (@roipeker)
- Added Docs and comments (@nipodemos)
... ... @@ -910,14 +796,12 @@ Getx 3.10 released with CLI and Get Server.
- Cleanup route code (@justkawal)
- Extension to facilitate insert widgets inside a CustomScrollView (@alexkharech)
- Fix docs .obs examples (@kai-oswald)
- Added tag capability to GetView
- Added tag capability to GetView
- Improve code separation of RouteManagement and Internacionalization
## [3.8.0]
- Added: Snackbar Status: Open, Opening, Closing and Closed
example:
example:
```dart
Get.snackbar('title', 'message', snackbarStatus: (status) {
if (status == SnackbarStatus.CLOSED) {
... ... @@ -927,24 +811,23 @@ Getx 3.10 released with CLI and Get Server.
```
## [3.7.0]
- Added: RxSet. Sets can now also be reactive.
- Added isDesktop/isMobile (@roipeker)
- Added isDesktop/isMobile (@roipeker)
- Improve GetPlatform: It is now possible to know which device the user is using if GetPlatform.isWeb is true.
context.responsiveValue used device orientation based on web and non-web applications. Now it checks if it is a desktop application (web or desktop application) to do the responsiveness calculation. (@roipeker)
context.responsiveValue used device orientation based on web and non-web applications. Now it checks if it is a desktop application (web or desktop application) to do the responsiveness calculation. (@roipeker)
- Change: The documentation previously stated that Iterables should not access the ".value" property.
However, many users did not pay attention to this fact, and ended up generating unnecessary issues and bugs in their application.
In this version, we focus on code security. Now ".value" is protected, so it cannot be accessed externally by Lists, Maps or Sets.
However, many users did not pay attention to this fact, and ended up generating unnecessary issues and bugs in their application.
In this version, we focus on code security. Now ".value" is protected, so it cannot be accessed externally by Lists, Maps or Sets.
- Change: Observable lists are now Dart Lists.
There is no difference in your use:
`RxList list = [].obs;`
And you use
`List list = [].obs;`
There is no difference in your use:
`RxList list = [].obs;`
And you use
`List list = [].obs;`
- Change: You do not need to access the ".value" property of primitives.
For Strings you need interpolation.
For num, int, double, you will have the normal operators, and use it as dart types.
This way, `.value` can be used exclusively in ModelClasses.
Example:
For Strings you need interpolation.
For num, int, double, you will have the normal operators, and use it as dart types.
This way, `.value` can be used exclusively in ModelClasses.
Example:
```dart
var name = "Jonny" .obs;
... ... @@ -964,92 +847,75 @@ The changes were not break changes, however, you may have missed the details of
The same goes for Maps and Sets.
## [3.6.2]
- Fix more formatting issues
## [3.6.1]
- Fix formatting issues
## [3.6.0]
- Added RxSet
- Change default logger to developer.log (@jorgegaticav)
- Added BindingsBuilder, ValueBuilder, and ObxValue (@roipeker)
- Added BindingsBuilder, ValueBuilder, and ObxValue (@roipeker)
- Fix fallback locale not working if missing country code (@thaihuynhxyz)
- Fix validation of email ".com.br"
## [3.5.1]
- Remove unnecessary whitespaces
## [3.5.0]
- Added logwritter (@stefandevo)
- Added responsiveValue (@juanjoseleca)
- Fixed ghost url for snackbar, bottomsheets, and dialogs and unnamed navigation.
## [3.4.6]
- Fix TextField dispose throw on last Flutter hotfix
## [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 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 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)
- Added fenix mode to Get.lazyPut.
Use `Get.lazyPut<Controller>(()=> Controller(), fenix:true)` to have a controller that after being destroyed, has the ability to be recreated in case someone needs it. This is a function that already exists in smartManagement.keepFactory which is now also possible in full mode.
- Added fenix mode to Get.lazyPut.
Use `Get.lazyPut<Controller>(()=> Controller(), fenix:true)` to have a controller that after being destroyed, has the ability to be recreated in case someone needs it. This is a function that already exists in smartManagement.keepFactory which is now also possible in full mode.
- Fix native transition on android
## [3.2.2]
- Improve transitions and refactor route system
## [3.2.1]
- Prevent black blackground on cupertino fullscreenDialog
## [3.2.0]
- Improve GetBuilder ram usage
- Added method update to Rx
Now you no longer need to make an entire class reactive to get an element update from it, you can simply call the update method of its instance, like this:
- Added method update to Rx
Now you no longer need to make an entire class reactive to get an element update from it, you can simply call the update method of its instance, like this:
```dart
class User{
User(this.name = '', this.age = 0);
String name;
String name;
int age;
}
... ... @@ -1066,43 +932,34 @@ user.age = 18;
Now is also possible to access a value without using the ".value". Just open and close parentheses.
In the previous example, you could do:
```dart
user().name; // before: user.value.name
```
And it is also possible to set a value without using the value, inserting the value directly into the variable.
```dart
user(User('João', 35)); // before: user.value = User('João', 35)
```
Added fenix mode to Get.lazyPut.
## [3.1.4]
## [3.1.4]
- Update readme banner
## [3.1.3]
- Activate unknownRoute on version 3
- Go back transitions.size and transitions.cupertino
## [3.1.2]
- Expose GetInstance
## [3.1.1]
- Improvement .obs methods
## [3.1.0]
- Added extensions to GetUtils and fix typo on GetUtils.isEmail (@stefandevo)
- Added .gitignore file (@hdeyana)
## [3.0.1]
- Breaking changes on Rx api and GetController and RxController were merged, and now you only have the 'GetxController'
- Refactor routing system. Now you can add custom transitions and more
- Improved the use of dynamic routes, you can now define two different pages according to your arguments.
... ... @@ -1113,93 +970,77 @@ Added fenix mode to Get.lazyPut.
- Added GetStorage (with separated package)
- Minor bug fixes.
## [2.14.0]
- Added getPages API.
## [2.14.0]
- Added getPages API.
- Deprecated namedPages
- Fix default transition
- Fix default transition
- Added Duration on Get.offAll(@kluverua)
## [2.13.1]
- Added sort to ListX
- Prepared the framework for version 3
## [2.13.0]
- Added Get.focusScope
## [2.13.0]
- Update docs
- Fix Bindings list on GetPageRoute
## [2.12.5]
- Update readme
## [2.12.4]
- Prevent exceptions on onReady with nullables
## [2.12.3]
- Fix List lenght == null
- Fix List lenght == null
## [2.12.2]
- Fix Workers
## [2.12.1]
- Added: onReady on Controllers LifeCycle
- Added: Observable maps
- Refactor: observable variables that now consume even less RAM.
## [2.11.3]
- Type parameters and added docs
## [2.11.2]
- Added docs
- Improvement performance of Obx
## [2.11.1]
- Fixed: oninit calling only once.
## [2.11.0]
- Added Permissions:
You can now revoke permissions to SmartManagement so that it cannot delete a particular controller.
Add to Get.put (Controller(), permanent: true); to make it indelible.
Get.lazyPut() will not receive this resource. Initially he had it, but we saw in internal tests that it could cause problems with the bindings API. Bindings were created to initialize and delete an instance, if it were allowed to make a controller started with lazyPut permanent, copies of that Controller would be created every time Binding was called. For the safety of users, especially new users who could easily do this, it was decided that this feature will only be present in Get.put.
You can now revoke permissions to SmartManagement so that it cannot delete a particular controller.
Add to Get.put (Controller(), permanent: true); to make it indelible.
Get.lazyPut() will not receive this resource. Initially he had it, but we saw in internal tests that it could cause problems with the bindings API. Bindings were created to initialize and delete an instance, if it were allowed to make a controller started with lazyPut permanent, copies of that Controller would be created every time Binding was called. For the safety of users, especially new users who could easily do this, it was decided that this feature will only be present in Get.put.
- Improve: Now a controller's life cycle has no connection with the View life cycle. It is no longer called internally in an "initState", it is now called when the Controller enters memory. This means that now onInit will always be called, regardless of where you started your dependency.
- removed: this property of the update() method has been permanently removed.
## [2.10.3]
- GetBuilder refactor. 11% reduction in RAM consumption and 2% in CPU consumption for the sample application. (using as base Flutter for linux desktop).
- The "this" property of the "update" method has been deprecated and will be removed in the next update. Please don't use it anymore. Just use "update()" now.
## [2.10.2]
- Fix Get.generalDialog default options
## [2.10.1]
- Fix broken links on pub
- Fix List empty error
## [2.10.0]
- Added SmartManagement, your application's memory is managed intelligently like never before!
- Added Obx, a widget that knows when to rebuild a child, without needing any type.
- Added MixinBuilder - If you need to use GetBuilder in conjunction with GetX, use GetxController with this widget, and the changes will occur either using update (this) or changing some reactive variable. Use only if necessary, for better RAM consumption, prefer widgets in that order:
Obx => GetX => GetBuilder => MixinBuilder.
Obx is the lightest of all, and MixinBuilder is a mix of the other 3, whenever possible, use the specific widget.
Obx => GetX => GetBuilder => MixinBuilder.
Obx is the lightest of all, and MixinBuilder is a mix of the other 3, whenever possible, use the specific widget.
- Refactor: StateManager of Get.
- Changed: full List API refactor, now value is no longer needed.
- Added Workers: You can hear changes to a variable and trigger custom callbacks.
... ... @@ -1207,140 +1048,111 @@ Added fenix mode to Get.lazyPut.
- Added Portuguese language to readme(@Nipodemos)
# [2.7.1]
- Improve list to set and get methods
## [2.7.0]
- Added obx, a simple state interceptor.
- Improve Bindings, ListX, and
- Added obx, a simple state interceptor.
- Improve Bindings, ListX, and
- fix docs typos e broken code (@ghprod)
## [2.6.3]
## [2.6.3]
- Flutter currently has a problem on some devices where using showModalBottomSheet() can cause TextFields to be hidden behind the keyboard (https://github.com/flutter/flutter/issues/18564) this issue is closed, even users reporting that the problem still occurs.
The problem happens casually, as well as the problem of the snackbar on the iPhone SE 2, and checking the code, I realized that a padding with MediaQuery.of(context).viewInsets.bottom is missing inside the bottomSheet to make it work correctly, since it does not have any constraint with the keyboard.
For stability, I decided not to use the standard Flutter bottomSheet, which contains many bugs, mainly related to keyboard padding, and the lack of respect for topBar's safeArea, and to use a proprietary bottomSheet implementation that is more stable. The Flutter dialog has no problem, so it will be used as the basis for Get.dialog. The bottomSheet will be based on the Flutter bottomSheet Raw API (\_ModalBottomSheetRoute), applying bug fixes.
The problem happens casually, as well as the problem of the snackbar on the iPhone SE 2, and checking the code, I realized that a padding with MediaQuery.of(context).viewInsets.bottom is missing inside the bottomSheet to make it work correctly, since it does not have any constraint with the keyboard.
For stability, I decided not to use the standard Flutter bottomSheet, which contains many bugs, mainly related to keyboard padding, and the lack of respect for topBar's safeArea, and to use a proprietary bottomSheet implementation that is more stable. The Flutter dialog has no problem, so it will be used as the basis for Get.dialog. The bottomSheet will be based on the Flutter bottomSheet Raw API (_ModalBottomSheetRoute), applying bug fixes.
- Added Get.isSnackbarOpen tests
## [2.6.2]
- Refactor Bindings API
## [2.6.1]
- Expose Bindings API
## [2.6.0]
- Added bindings.
You can now add bindings from your controllers to your routes, to prepare GetBuilder or GetX to create a dependency already declared in a Binding class. This feature is in an experimental phase, and will not be documented until the end of the tests.
You can now add bindings from your controllers to your routes, to prepare GetBuilder or GetX to create a dependency already declared in a Binding class. This feature is in an experimental phase, and will not be documented until the end of the tests.
## [2.5.10]
- Removed remnants of previousArgs on routeObserver.
This feature had been deprecated in previous updates, and was removed in version 2.5.8. Some remaining references on the routeObserver were causing exceptions in version 2.5.9, and were removed completely in version 2.5.10.
This feature had been deprecated in previous updates, and was removed in version 2.5.8. Some remaining references on the routeObserver were causing exceptions in version 2.5.9, and were removed completely in version 2.5.10.
## [2.5.9]
- Fix Get.find with named instance
## [2.5.8]
- Added docs
- Added tests(@chimon2000)
## [2.5.7]
- Fix Get.generalDialog optionals
- Added GetX onInit support
## [2.5.6]
- GetBuilder refactor to work with lazyPut.
Now you can list your controllers in advance with Get.lazyPut, and only when it is called for the first time will it be relocated in memory.
Now you can list your controllers in advance with Get.lazyPut, and only when it is called for the first time will it be relocated in memory.
- Fix english typos(@gumbarros)
## [2.5.5]
- Fix arguments broken by new methods
## [2.5.4]
- Refactor methods
## [2.5.3]
- Fix snackbar padding on iPhone SE 2.
- Added themes docs
- Added ThemeMode (@RodBr)
## [2.5.2]
- Fix: key not found when Get.key is used with no MaterialApp
## [2.5.1]
- Improve - GetBuilder uses 18% less ram on more of 20 controllers.
## [2.5.0]
- Added List.obs
- Now you can transform any class on obs
## [2.4.0]
- Added GetX, state manager rxDart based.
## [2.4.0]
- Added GetX, state manager rxDart based.
- Fix error on add for non global controllers
## [2.3.2]
## [2.3.2]
- Fix close method called on not root GetBuilder
## [2.3.1]
## [2.3.1]
- Auto close stream inside close method
- Added docs
## [2.3.0]
## [2.3.0]
- Added interface to GetX support
## [2.2.8]
## [2.2.8]
- Added api to platform brightness
## [2.2.7]
## [2.2.7]
- Fix typos
## [2.2.6]
## [2.2.6]
- Fix cancel button on defaultDialog don't appear when widget implementation usage
## [2.2.5]
## [2.2.5]
- Refator defaultDialog
## [2.2.4]
## [2.2.4]
- Clean code
- Fix Get.LazyPut
## [2.2.3]
## [2.2.3]
- Remove defaultDialog type
## [2.2.2]
## [2.2.2]
- Fix GetRoute not found
## [2.2.1]
## [2.2.1]
- Improve lazyPut and fix tag to lazyput(@rochadaniel)
## [2.2.0]
## [2.2.0]
- Added: Ability to choose or delay a widget's state change according to its ID.
- Added: Ability to fire triggers when loading materialApp.
- Added: Ability to change theme dynamically.
... ... @@ -1348,315 +1160,274 @@ Added fenix mode to Get.lazyPut.
- Added: Ability to trigger events on the MaterialApp.
- Added: Get.lazyPut (lazy loading of dependencies).
- Added: Get.creator - a factory of dependencies .
- Added: Capability of define abstract class on dependencies.
## [2.1.2]
- Added: Capability of define abstract class on dependencies.
## [2.1.2]
- Get.defaultDialog refactor
## [2.1.1]
## [2.1.1]
- fix typo
## [2.1.0]
## [2.1.0]
- Added Get.rawSnackbar
- Added instantInit config to snackbars
- Refactor Get Instance Manager
- Improved performance and bug fix to Get State Manager
- Improved performance and bug fix to Get State Manager
- Improved performance of GetRoute on namedRoutes
- Hotfix on namedRoutes
## [2.0.10]
## [2.0.10]
- Bump new Flutter version
- Added Get.generalDialog
## [2.0.6]
## [2.0.6]
- Fix typo on readme
## [2.0.5]
## [2.0.5]
- Changing the bottomsheet API to comply with the documentation.
## [2.0.4]
## [2.0.4]
- Fix type not found in some versions of Flutter stable
## [2.0.3]
## [2.0.3]
- Update Docs
## [2.0.2]
## [2.0.2]
- Update GetObserver
## [2.0.1]
## [2.0.1]
- Fix docs and typos
## [2.0.0]
## [2.0.0]
- Added easy state manager
- Change dialog API
- Added GetMaterialApp
- Added new experimental APIs
- Improve Observer
- Added default duration on Transitions
- Change dialog API
- Added GetMaterialApp
- Added new experimental APIs
- Improve Observer
- Added default duration on Transitions
- Added new routeNamed sistem
- Added Global stateManager config
- Improve Get instance manager
- Added routingCallback
- Added closeOverlays to Get.back
- Added dynamic urls
- Added Global stateManager config
- Improve Get instance manager
- Added routingCallback
- Added closeOverlays to Get.back
- Added dynamic urls
- Cleaner code
- Improve lib performance
- Improve lib performance
- Many others minor APIs added
## [1.20.1]
## [1.20.1]
- Improve: Get.finds
## [1.20.0]
## [1.20.0]
- Added Get Instance Manager
Get.put / Get.find / Get.delete
## [1.19.1]
## [1.19.1]
- Fix default transitions for namedRoutes
## [1.19.0]
## [1.19.0]
- Added nested navigators
## [1.18.0]
## [1.18.0]
- Added SafeArea to bottomsheets
- Added docs
## [1.17.0]
## [1.17.0]
- Added experimental APIs
## [1.16.1]
## [1.16.1]
- Improve: GetObserver
## [1.16.0-dev]
## [1.16.0-dev]
- Added Get config
- Added logEnable
- Added Default transition
- Added default popGesture behaviour
- Added overlayContext
- Added logEnable
- Added Default transition
- Added default popGesture behaviour
- Added overlayContext
- Fix Duration transition
## [1.14.1-dev]
## [1.14.1-dev]
- Fix ternary on new dart version
## [1.14.0-dev]
## [1.14.0-dev]
- Added compatibility with Flutter 1.17.1
- Added back popGesture to iOS (default) and Android (optional)
- Improve performance
- Decrease lib size to 94.9kb (25.4k after compiled on release)
## [1.13.1-dev]
## [1.13.1-dev]
- Fix back function
## [1.13.0-dev]
## [1.13.0-dev]
- Plugin refactor
- Added GetPlatform
## [1.12.0-dev]
## [1.12.0-dev]
-Compatibility with Dev branch
## [1.11.4]
## [1.11.4]
- Refactor code of library
## [1.11.3]
## [1.11.3]
-Added docs
## [1.11.2]
-Fix flutter web platform and added GetPlatform
## [1.11.1]
## [1.11.2]
-Fix flutter web platform and added GetPlatform
-Improve swipe to back on iOS devices
## [1.11.1]
-Improve swipe to back on iOS devices
## [1.11.0]
## [1.11.0]
-Added experimental GetCupertino
-Added experimental GetCupertino
## [1.10.5]
-Added setKey to improve modular compatibility
-Added ability to define transition duration directly when calling the new route.
## [1.10.5]
## [1.10.4]
-Improve Get.offAll() - predicate now is optional
-Added setKey to improve modular compatibility
-Added ability to define transition duration directly when calling the new route.
## [1.10.3]
-Improve default color from dialogs
## [1.10.4]
## [1.10.2]
-Improve snackbar text color
-Added background color to snackbar (@claudneysessa)
-Improve Get.offAll() - predicate now is optional
## [1.10.1]
-Backdrop improvement
## [1.10.3]
## [1.10.0]
-Added backdrop
-Improve default color from dialogs
## [1.9.2]
-Added docs to GetObserver
## [1.10.2]
## [1.9.1]
-Fix typo on snackbar route
-Improve snackbar text color
-Added background color to snackbar (@claudneysessa)
## [1.9.0]
-Added: Navigator observer
-Added: Get.args to named routes
-Improve snackbar performance
## [1.10.1]
## [1.8.1]
-Fix new snackbar features
-Backdrop improvement
## [1.8.0]
-Add Get.close method.
-Add many Snackbars features
## [1.10.0]
## [1.7.4]
-Fix dialog child error
-Added backdrop
## [1.7.3]
-Added transitions docs
## [1.9.2]
## [1.7.2]
-Fix bottomsheet on macos
-Added docs to GetObserver
## [1.7.1]
-Fix docs
## [1.9.1]
## [1.7.0]
- Improve geral performance. Get.to Wrap now consumes even less RAM and CPU. In an application with 20 screens, it obtained 82% less RAM usage compared to the traditional method Navigator.push and had a CPU normalization of 23% in a Moto z2, against 64% CPU usage in Navigator.push with MaterialPageRoute. Test it for yourself!
- Added BottomSheet with no context
- Added modern Blur Snackbar
- Added customs transitions
- Improve dialogs performance
-Fix typo on snackbar route
## [1.6.4]
- Improve performance.
## [1.9.0]
## [1.6.3]
- Clean code.
-Added: Navigator observer
-Added: Get.args to named routes
-Improve snackbar performance
## [1.6.2]
- Fix bugs on blurred Snackbars
## [1.8.1]
## [1.6.1]
- Add docs and improve performance
## [1.6.0]
- Add support to snackbars
-Fix new snackbar features
## [1.5.0+1]
- Add color and opacity to dialogs
## [1.5.0]
- Add support to dialogs
## [1.8.0]
## [1.4.0+7]
- Add more documentation
-Add Get.close method.
-Add many Snackbars features
## [1.4.0+6]
## [1.7.4]
- Improve performance and bug fix
-Fix dialog child error
## [1.4.0]
## [1.7.3]
-Added transitions docs
## [1.7.2]
-Fix bottomsheet on macos
## [1.7.1]
-Fix docs
## [1.7.0]
- Improve geral performance. Get.to Wrap now consumes even less RAM and CPU. In an application with 20 screens, it obtained 82% less RAM usage compared to the traditional method Navigator.push and had a CPU normalization of 23% in a Moto z2, against 64% CPU usage in Navigator.push with MaterialPageRoute. Test it for yourself!
- Added BottomSheet with no context
- Added modern Blur Snackbar
- Added customs transitions
- Improve dialogs performance
## [1.6.4]
- Improve performance.
## [1.6.3]
- Clean code.
## [1.6.2]
- Fix bugs on blurred Snackbars
## [1.6.1]
- Add docs and improve performance
## [1.6.0]
- Add support to snackbars
## [1.5.0+1]
- Add color and opacity to dialogs
## [1.5.0]
- Add support to dialogs
## [1.4.0+7]
- Add more documentation
## [1.4.0+6]
- Improve performance and bug fix
## [1.4.0]
- Added Get.removeRoute // ability to remove one route.
Get.until // back repeatedly until the predicate returns true.
Get.offUntil // go to next route and remove all the previous routes until the predicate returns true.
Get.offNamedUntil // go to next named route and remove all the previous routes until the predicate returns true.
## [1.3.4]
- Added Get.removeRoute // ability to remove one route.
Get.until // back repeatedly until the predicate returns true.
Get.offUntil // go to next route and remove all the previous routes until the predicate returns true.
Get.offNamedUntil // go to next named route and remove all the previous routes until the predicate returns true.
## [1.3.4]
- Improve performance
## [1.3.3]
## [1.3.3]
- Fix Get.back arguments
## [1.3.2]
## [1.3.2]
- Improve performance
## [1.3.1]
## [1.3.1]
- Update docs
## [1.3.0]
## [1.3.0]
- Update docs, readme, and add full support to flutter_web
## [1.2.1]
## [1.2.1]
- Fix bug currentState = null
## [1.2.0]
## [1.2.0]
- Add routes navigation with no context
## [1.1.0]
## [1.1.0]
- Add support to named routes
- Add support to named routes
## [1.0.3]
## [1.0.3]
- Improve Performance
## [1.0.2]
## [1.0.2]
- Add examples
## [1.0.1]
## [1.0.1]
- Doc changes
## [1.0.0]
## [1.0.0]
- initial release
... ...
... ... @@ -543,6 +543,7 @@ class HomeProvider extends GetConnect {
//HttpStatus.unauthorized
httpClient.maxAuthRetries = 3;
}
}
@override
Future<Response<CasesModel>> getCases(String path) => get(path);
... ...
... ... @@ -498,6 +498,7 @@ class HomeProvider extends GetConnect {
//HttpStatus.unauthorized
httpClient.maxAuthRetries = 3;
}
}
@override
Future<Response<CasesModel>> getCases(String path) => get(path);
... ...
... ... @@ -98,7 +98,7 @@
- **조직화:** GetX는 화면, 프레젠테이션 로직, 비즈니스 로직, 종속성 주입 및 네비게이션을 완전히 분리 할 수 있습니다. 라우트간 전환을 하는데에 컨텍스트가 필요하지 않아 위젯 트리(시각객체)에 독립적입니다. inheritedWidget을 통해 컨트롤러/블록에 접근하는 데 컨텍스트가 필요하지 않아 시각화 계층에서 프레젠테이션 로직과 비즈니스 로직을 완전히 분리됩니다. 이 GetX는 자체 종속성 주입 기능을 사용하여 DI를 뷰에서 완전히 분리하기 때문에 다중 Provider를 통해 위젯 트리에서 컨트롤러/모델/블록으로 주입 할 필요가 없습니다.
GetX를 사용하면 기본적으로 클린 코드를 가지게 되어 애플리케이션의 각 기능을 쉽게 찾을 수 있습니다. 이것은 유지 보수를 용이하게 하며 모듈의 공유가 가능하고 Flutter에서는 생각할 수 없었던 것들도 전부 가능합니다.
GetX를 사용하면 기본적으로 클린 코드를 가지게 되어 애플리케이션의 각 기능을 쉽게 찾을 수있습니다. 이것은 유지 보수를 용이하게 하며 모듈의 공유가 가능하고 Flutter에서는 생각할 수 없었던 것들도 전부 가능합니다.
BLoC은 Flutter에서 코드를 구성하기 위한 시작점으로 비즈니스 로직과 시각객체를 분리합니다. Getx는 비즈니스 로직 뿐만 아니라 프레젠테이션 로직을 분리하는 자연스러운 진화입니다. 추가로 종속성 주입과 라우트 또한 분리되고 데이터 계층이 모두로부터 분리됩니다. Hello World를 구현하는 것보다 더 쉽게 모든 것이 어디 있는지 알수 있습니다.
Flutter SDK와 함께 GetX를 사용하면 가장 쉽고 실용적이며 확장 가능한 고성능 어플리케이션을 만들수 있습니다. 초보자에게는 쉬우며 전문가에게는 정확하고 완벽하게 동작하는 대규모 생태계가 함께합니다. 안전하고 안정적이며 업데이트되고 기본 Flutter SDK에 없는 광범위한 API 빌드를 제공합니다.
... ... @@ -129,7 +129,7 @@ import 'package:get/get.dart';
# GetX를 사용한 Counter 앱
Flutter의 새 프로젝트에서 기본적으로 생성 되는 "counter" 프로젝트는 100줄이 넘습니다 (코멘트 포함). Get의 강력함을 보여주기 위해 클릭 할 때마다 상태를 변경하고, 페이지 사이를 전환하고, 화면 사이의 상태를 공유하는 "counter"를 만드는 방법을 주석이 포함된 26줄의 코드로 보여줄 것입니다.
Flutter의 새 프로젝트에서 기본적으로 생성 되는 "counter" 프로젝트는 100줄이 넘습니다 (코멘트 포함). Get의 을 보여주기 위해 클릭 할 때마다 상태를 변경하고, 페이지 사이를 전환하고, 화면 사이의 상태를 공유하는 "counter"를 만드는 방법을 주석이 포함된 26줄의 코드로 보여줄 것입니다.
- 1 단계:
MaterialApp 에 "Get"을 추가하여 GetMaterialApp 으로 변경합니다.
... ...
![](https://raw.githubusercontent.com/jonataslaw/getx-community/master/get.png)
[![pub package](https://img.shields.io/pub/v/get.svg?label=get&color=blue)](https://pub.dev/packages/get)
[![popularity](https://img.shields.io/pub/popularity/get?logo=dart)](https://pub.dev/packages/get/score)
[![likes](https://img.shields.io/pub/likes/get?logo=dart)](https://pub.dev/packages/get/score)
[![pub points](https://img.shields.io/pub/points/sentry?logo=dart)](https://pub.dev/packages/get/score)
[![popularity](https://badges.bar/get/popularity)](https://pub.dev/packages/sentry/score)
[![likes](https://badges.bar/get/likes)](https://pub.dev/packages/get/score)
[![pub points](https://badges.bar/get/pub%20points)](https://pub.dev/packages/get/score)
![building](https://github.com/jonataslaw/get/workflows/build/badge.svg)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://pub.dev/packages/effective_dart)
[![Discord Shield](https://img.shields.io/discord/722900883784073290.svg?logo=discord)](https://discord.com/invite/9Hpt99N)
... ... @@ -34,10 +34,8 @@
[![Korean](https://img.shields.io/badge/Language-Korean-blueviolet?style=for-the-badge)](README.ko-kr.md)
[![French](https://img.shields.io/badge/Language-French-blueviolet?style=for-the-badge)](README-fr.md)
[![Japanese](https://img.shields.io/badge/Language-Japanese-blueviolet?style=for-the-badge)](README.ja-JP.md)
[![Hindi](https://img.shields.io/badge/Language-Hindi-blueviolet?style=for-the-badge)](README-hi.md)
[![Bangla](https://img.shields.io/badge/Language-Bangla-blueviolet?style=for-the-badge)](README-bn.md)
</div>
- [About Get](#about-get)
... ... @@ -518,6 +516,7 @@ class HomeProvider extends GetConnect {
//HttpStatus.unauthorized
httpClient.maxAuthRetries = 3;
}
}
@override
Future<Response<CasesModel>> getCases(String path) => get(path);
... ... @@ -681,19 +680,19 @@ context.height
context.heightTransformer()
context.widthTransformer()
/// Similar to MediaQuery.sizeOf(context);
/// Similar to MediaQuery.of(context).size
context.mediaQuerySize()
/// Similar to MediaQuery.paddingOf(context);
/// Similar to MediaQuery.of(context).padding
context.mediaQueryPadding()
/// Similar to MediaQuery.viewPaddingOf(context);
/// Similar to MediaQuery.of(context).viewPadding
context.mediaQueryViewPadding()
/// Similar to MediaQuery.viewInsetsOf(context);
/// Similar to MediaQuery.of(context).viewInsets;
context.mediaQueryViewInsets()
/// Similar to MediaQuery.orientationOf(context);
/// Similar to MediaQuery.of(context).orientation;
context.orientation()
/// Check if device is on landscape mode
... ... @@ -702,10 +701,10 @@ context.isLandscape()
/// Check if device is on portrait mode
context.isPortrait()
/// Similar to MediaQuery.devicePixelRatioOf(context);
/// Similar to MediaQuery.of(context).devicePixelRatio;
context.devicePixelRatio()
/// Similar to MediaQuery.textScaleFactorOf(context);
/// Similar to MediaQuery.of(context).textScaleFactor;
context.textScaleFactor()
/// Get the shortestSide from screen
... ... @@ -1275,5 +1274,3 @@ Any contribution is welcome!
- [Flutter State Management with GetX – Complete App](https://www.appwithflutter.com/flutter-state-management-with-getx/) - by App With Flutter.
- [Flutter Routing with Animation using Get Package](https://www.appwithflutter.com/flutter-routing-using-get-package/) - by App With Flutter.
- [A minimal example on dartpad](https://dartpad.dev/2b3d0d6f9d4e312c5fdbefc414c1727e?) - by [Roi Peker](https://github.com/roipeker)
- [GetConnect: The best way to perform API operations in Flutter with Get.](https://absyz.com/getconnect-the-best-way-to-perform-api-operations-in-flutter-with-getx/) - by [MD Sarfaraj](https://github.com/socialmad)
- [How To Create an App with GetX Architect in Flutter with Get CLI](https://www.youtube.com/watch?v=7mb4qBA7kTk&t=1380s) - by [MD Sarfaraj](https://github.com/socialmad)
... ...
... ... @@ -440,6 +440,7 @@ class HomeProvider extends GetConnect {
//HttpStatus.unauthorized
httpClient.maxAuthRetries = 3;
}
}
@override
Future<Response<CasesModel>> getCases(String path) => get(path);
... ...
... ... @@ -37,17 +37,6 @@ _语言: 中文, [英文](README.md), [越南文](README-vi.md), [印度尼西
- [改变语言](#改变语言)
- [系统语言](#系统语言)
- [改变主题](#改变主题)
- [GetConnect](#getconnect)
- [默认配置](#默认配置)
- [自定义配置](#自定义配置)
- [GetPage 中间件](#getpage-中间件)
- [优先级](#优先级)
- [Redirect](#redirect)
- [onPageCalled](#onpagecalled)
- [OnBindingsStart](#onbindingsstart)
- [OnPageBuildStart](#onpagebuildstart)
- [OnPageBuilt](#onpagebuilt)
- [OnPageDispose](#onpagedispose)
- [其他高级API](#其他高级api)
- [可选的全局设置和手动配置](#可选的全局设置和手动配置)
- [局部状态组件](#局部状态组件)
... ... @@ -405,162 +394,6 @@ Get.changeTheme(Get.isDarkMode? ThemeData.light(): ThemeData.dark());
`.darkmode`被激活时,它将切换到light主题,当light主题被激活时,它将切换到dark主题。
## GetConnect
GetConnect可以便捷的通过http或websockets进行前后台通信。
### 默认配置
你能轻松的通过extend GetConnect就能使用GET/POST/PUT/DELETE/SOCKET方法与你的Rest API或websockets通信。
```dart
class UserProvider extends GetConnect {
// Get request
Future<Response> getUser(int id) => get('http://youapi/users/$id');
// Post request
Future<Response> postUser(Map data) => post('http://youapi/users', body: data);
// Post request with File
Future<Response<CasesModel>> postCases(List<int> image) {
final form = FormData({
'file': MultipartFile(image, filename: 'avatar.png'),
'otherFile': MultipartFile(image, filename: 'cover.png'),
});
return post('http://youapi/users/upload', form);
}
GetSocket userMessages() {
return socket('https://yourapi/users/socket');
}
}
```
### 自定义配置
GetConnect具有多种自定义配置。你可以配置base Url,配置响应,配置请求,添加权限验证,甚至是尝试认证的次数,除此之外,还可以定义一个标准的解码器,该解码器将把您的所有请求转换为您的模型,而不需要任何额外的配置。
```dart
class HomeProvider extends GetConnect {
@override
void onInit() {
// All request will pass to jsonEncode so CasesModel.fromJson()
httpClient.defaultDecoder = CasesModel.fromJson;
httpClient.baseUrl = 'https://api.covid19api.com';
// baseUrl = 'https://api.covid19api.com'; // It define baseUrl to
// Http and websockets if used with no [httpClient] instance
// It's will attach 'apikey' property on header from all requests
httpClient.addRequestModifier((request) {
request.headers['apikey'] = '12345678';
return request;
});
// Even if the server sends data from the country "Brazil",
// it will never be displayed to users, because you remove
// that data from the response, even before the response is delivered
httpClient.addResponseModifier<CasesModel>((request, response) {
CasesModel model = response.body;
if (model.countries.contains('Brazil')) {
model.countries.remove('Brazilll');
}
});
httpClient.addAuthenticator((request) async {
final response = await get("http://yourapi/token");
final token = response.body['token'];
// Set the header
request.headers['Authorization'] = "$token";
return request;
});
//Autenticator will be called 3 times if HttpStatus is
//HttpStatus.unauthorized
httpClient.maxAuthRetries = 3;
}
@override
Future<Response<CasesModel>> getCases(String path) => get(path);
}
```
## GetPage 中间件
GetPage现在有个新的参数可以把列表中的Get中间件按指定顺序执行。
**注意**: 当GetPage有中间件时,所有的子page会自动有相同的中间件。
### 优先级
设置中间件的优先级定义Get中间件的执行顺序。
```dart
final middlewares = [
GetMiddleware(priority: 2),
GetMiddleware(priority: 5),
GetMiddleware(priority: 4),
GetMiddleware(priority: -8),
];
```
这些中间件会按这个顺序执行 **-8 => 2 => 4 => 5**
### Redirect
当被调用路由的页面被搜索时,这个函数将被调用。它将RouteSettings作为重定向的结果。或者给它null,就没有重定向了。
```dart
RouteSettings redirect(String route) {
final authService = Get.find<AuthService>();
return authService.authed.value ? null : RouteSettings(name: '/login')
}
```
### onPageCalled
在调用页面时,创建任何东西之前,这个函数会先被调用。
您可以使用它来更改页面的某些内容或给它一个新页面。
```dart
GetPage onPageCalled(GetPage page) {
final authService = Get.find<AuthService>();
return page.copyWith(title: 'Welcome ${authService.UserName}');
}
```
### OnBindingsStart
这个函数将在绑定初始化之前被调用。
在这里,您可以更改此页面的绑定。
```dart
List<Bindings> onBindingsStart(List<Bindings> bindings) {
final authService = Get.find<AuthService>();
if (authService.isAdmin) {
bindings.add(AdminBinding());
}
return bindings;
}
```
### OnPageBuildStart
这个函数将在绑定初始化之后被调用。
在这里,您可以在创建绑定之后和创建页面widget之前执行一些操作。
```dart
GetPageBuilder onPageBuildStart(GetPageBuilder page) {
print('bindings are ready');
return page;
}
```
### OnPageBuilt
这个函数将在GetPage.page调用后被调用,并给出函数的结果,并获取将要显示的widget。
### OnPageDispose
这个函数将在处理完页面的所有相关对象(Controllers, views, ...)之后被调用。
## 其他高级API
```dart
... ...
# Include option is buggy:
include: package:flutter_lints/flutter.yaml
# https://github.com/flutter/flutter/issues/62591
# In case the include issue gets fixed, lines below INCLUDE_FIX
# can be removed
# include: package:flutter_lints/flutter.yaml
# include: package:effective_dart/analysis_options.1.2.0.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
await_only_futures: true
# This one is desirable, but that's a lot of work for now
public_member_api_docs: false
# Desirable, but would be breaking changes:
avoid_positional_boolean_parameters: false
constant_identifier_names: false
include_file_not_found: false
# INCLUDE_FIX (copy of effective dart 1.2.0)
# STYLE
camel_case_types: true
close_sinks: true
unnecessary_statements: true
camel_case_extensions: true
library_names: true
file_names: true
library_prefixes: true
non_constant_identifier_names: true
directives_ordering: true
lines_longer_than_80_chars: true # avoid
curly_braces_in_flow_control_structures: true
# DOCUMENTATION
slash_for_doc_comments: true
package_api_docs: true # prefer
#- comment_references # Unused because https://github.com/dart-lang/sdk/issues/36974
# USAGE
implementation_imports: true
avoid_relative_lib_imports: true # prefer
prefer_relative_imports: true # prefer
prefer_adjacent_string_concatenation: true
prefer_interpolation_to_compose_strings: true # prefer
unnecessary_brace_in_string_interps: true # avoid
prefer_collection_literals: true
avoid_function_literals_in_foreach_calls: true # avoid
prefer_iterable_whereType: true
prefer_function_declarations_over_variables: true
unnecessary_lambdas: true
prefer_equal_for_default_values: true
avoid_init_to_null: true
unnecessary_getters_setters: true
annotate_overrides: true
#- unnecessary_getters # prefer # Disabled pending fix: https://github.com/dart-lang/linter/issues/23
#- prefer_expression_function_bodies # consider
unnecessary_this: true
prefer_initializing_formals: true
type_init_formals: true
empty_constructor_bodies: true
unnecessary_new: true
unnecessary_const: true
avoid_catches_without_on_clauses: true # avoid
avoid_catching_errors: true
use_rethrow_when_possible: true
unrelated_type_equality_checks: true
# DESIGN
use_to_and_as_if_applicable: true # prefer
one_member_abstracts: true # avoid
avoid_classes_with_only_static_members: true # avoid
prefer_mixin: true
prefer_final_fields: true # prefer
use_setters_to_change_properties: true
avoid_setters_without_getters: true
avoid_returning_null: true # avoid
avoid_returning_this: true # avoid
type_annotate_public_apis: true # prefer
#- prefer_typing_uninitialized_variables # consider
omit_local_variable_types: true # avoid
avoid_types_on_closure_parameters: true # avoid
avoid_return_types_on_setters: true # avoid
prefer_generic_function_type_aliases: true
avoid_private_typedef_functions: true # prefer
#- use_function_type_syntax_for_parameters # consider
hash_and_equals: true
avoid_equals_and_hash_code_on_mutable_classes: true # avoid
avoid_null_checks_in_equality_operators: true
... ...
... ... @@ -507,7 +507,7 @@ GetBuilder<Controller>(
* You have already learned how to manage states with Get.
* Note: You may want a larger organization, and not use the init property. For that, you can create a class and extends Binding class, and within it mention the controllers that will be created within that route. Controllers will not be created at that time, on the contrary, this is just a statement, so that the first time you use a Controller, Get will know where to look. Get will remain lazyLoad, and will continue to dispose Controllers when they are no longer needed. See the pub.dev example to see how it works.
* Note: You may want a larger organization, and not use the init property. For that, you can create a class and extends Bindings class, and within it mention the controllers that will be created within that route. Controllers will not be created at that time, on the contrary, this is just a statement, so that the first time you use a Controller, Get will know where to look. Get will remain lazyLoad, and will continue to dispose Controllers when they are no longer needed. See the pub.dev example to see how it works.
If you navigate many routes and need data that was in your previously used controller, you just need to use GetBuilder Again (with no init):
... ...
... ... @@ -24,7 +24,7 @@
# State Management
GetX does not use Streams or ChangeNotifier like other state managers. Why? In addition to building applications for android, iOS, web, windows, macos and linux, with GetX you can build server applications with the same syntax as Flutter/GetX. In order to improve response time and reduce RAM consumption, we created GetValue and GetStream, which are low latency solutions that deliver a lot of performance, at a low operating cost. We use this base to build all of our resources, including state management.
GetX does not use Streams or ChangeNotifier like other state managers. Why? In addition to building applications for android, iOS, web, linux, macos and linux, with GetX you can build server applications with the same syntax as Flutter/GetX. In order to improve response time and reduce RAM consumption, we created GetValue and GetStream, which are low latency solutions that deliver a lot of performance, at a low operating cost. We use this base to build all of our resources, including state management.
* _Complexity_: Some state managers are complex and have a lot of boilerplate. With GetX you don't have to define a class for each event, the code is highly clean and clear, and you do a lot more by writing less. Many people have given up on Flutter because of this topic, and they now finally have a stupidly simple solution for managing states.
* _No code generators_: You spend half your development time writing your application logic. Some state managers rely on code generators to have minimally readable code. Changing a variable and having to run build_runner can be unproductive, and often the waiting time after a flutter clean will be long, and you will have to drink a lot of coffee.
... ... @@ -450,7 +450,7 @@ All workers returns a `Worker` instance, that you can use to cancel ( via `dispo
* **`interval`**
'interval' is different from the debouce. debouce if the user makes 1000 changes to a variable within 1 second, he will send only the last one after the stipulated timer (the default is 800 milliseconds). Interval will instead ignore all user actions for the stipulated period. If you send events for 1 minute, 1000 per second, debounce will only send you the last one, when the user stops strafing events. interval will deliver events every second, and if set to 3 seconds, it will deliver 20 events that minute. This is recommended to avoid abuse, in functions where the user can quickly click on something and get some advantage (imagine that the user can earn coins by clicking on something, if he clicked 300 times in the same minute, he would have 300 coins, using interval, you can set a time frame for 3 seconds, and even then clicking 300 or a thousand times, the maximum he would get in 1 minute would be 20 coins, clicking 300 or 1 million times). The debounce is suitable for anti-DDos, for functions like search where each change to onChange would cause a query to your api. Debounce will wait for the user to stop typing the name, to make the request. If it were used in the coin scenario mentioned above, the user would only win 1 coin, because it is only executed, when the user "pauses" for the established time.
'interval' is different from the debouce. debouce if the user makes 1000 changes to a variable within 1 second, he will send only the last one after the stipulated timer (the default is 800 milliseconds). Interval will instead ignore all user actions for the stipulated period. If you send events for 1 minute, 1000 per second, debounce will only send you the last one, when the user stops strafing events. interval will deliver events every second, and if set to 3 seconds, it will deliver 20 events that minute. This is recommended to avoid abuse, in functions where the user can quickly click on something and get some advantage (imagine that the user can earn coins by clicking on something, if he clicked 300 times in the same minute, he would have 300 coins, using interval, you you can set a time frame for 3 seconds, and even then clicking 300 or a thousand times, the maximum he would get in 1 minute would be 20 coins, clicking 300 or 1 million times). The debounce is suitable for anti-DDos, for functions like search where each change to onChange would cause a query to your api. Debounce will wait for the user to stop typing the name, to make the request. If it were used in the coin scenario mentioned above, the user would only win 1 coin, because it is only executed, when the user "pauses" for the established time.
* NOTE: Workers should always be used when starting a Controller or Class, so it should always be on onInit (recommended), Class constructor, or the initState of a StatefulWidget (this practice is not recommended in most cases, but it shouldn't have any side effects).
... ... @@ -507,7 +507,7 @@ GetBuilder<Controller>(
* You have already learned how to manage states with Get.
* Note: You may want a larger organization, and not use the init property. For that, you can create a class and extends Binding class, and within it mention the controllers that will be created within that route. Controllers will not be created at that time, on the contrary, this is just a statement, so that the first time you use a Controller, Get will know where to look. Get will remain lazyLoad, and will continue to dispose Controllers when they are no longer needed. See the pub.dev example to see how it works.
* Note: You may want a larger organization, and not use the init property. For that, you can create a class and extends Bindings class, and within it mention the controllers that will be created within that route. Controllers will not be created at that time, on the contrary, this is just a statement, so that the first time you use a Controller, Get will know where to look. Get will remain lazyLoad, and will continue to dispose Controllers when they are no longer needed. See the pub.dev example to see how it works.
If you navigate many routes and need data that was in your previously used controller, you just need to use GetBuilder Again (with no init):
... ...
... ... @@ -73,7 +73,7 @@ Get.put<S>(
```
### Get.lazyPut
인스턴스 사용하는 경우에만 의존성을 lazyLoad 할 수 있습니다. 계산 비용이 많이 드는 클래스나 한곳에서 다양한 클래스를 당장 사용하지 않으면서 인스턴스화 하기를 원한다면(Bindings 클래스처럼) 매우 유용합니다.
인스턴스하게 사용하는 경우에만 의존성을 lazyLoad 할 수 있습니다. 계산 비용이 많이 드는 클래스나 한곳에서 다양한 클래스를 당장 사용하지 않으면서 인스턴스화 하기를 원한다면(Bindings 클래스처럼) 매우 유용합니다.
```dart
/// ApiMock은 처음으로 Get.find<ApiMock>을 사용하는 경우에만 호출됩니다.
... ... @@ -94,7 +94,7 @@ Get.lazyPut<Controller>( () => Controller() )
lazyPut을 사용시 설정 가능한 모든 사항:
```dart
Get.lazyPut<S>(
// 필수: 이 메서드는 처음으로 클래스가 호출할 때 실행될 것입니다.
// 필수: 이 메서드는 처음으로 클래스가 호출할 때 실행될 것입니다
InstanceBuilderCallback builder,
// 선택: Get.put()과 같이 같은 클래스를 다중으로 인스턴스할 경우 사용합니다.
... ... @@ -148,7 +148,7 @@ Get.Create<SomeClass>(() => SomeClass());
Get.Create<LoginController>(() => LoginController());
```
create 사용 시 설정 가능한 모든 사항:
create 사용시 설정 가능한 모든 사항:
```dart
Get.create<S>(
... ... @@ -177,7 +177,7 @@ final controller = Get.find<Controller>();
// OR
Controller controller = Get.find();
// 그렇습니다. 마법 같아요. Get은 controller를 찾아 가져다 줍니다.
// 그렇습니다. 마법 같아요. Get은 controller를 찾고 배달해 줍니다.
// Get은 백만개의 contrller를 인스턴스화해서 가질수 있고 항상 올바르게 전달해 줍니다.
```
... ... @@ -200,35 +200,6 @@ Get의 인스턴스에서 삭제합니다:
Get.delete<Controller>(); // 보통 GetX는 미사용 controller를 삭제하기 때문에 수행할 필요가 없습니다
```
## 대체 인스턴스 지정
현재 추가된 인스턴스는 `replace` 또는 `lazyReplace` 메소드를 사용하여 유사하거나 확장된 클래스 인스턴스로 교체할 수 있습니다. 이후 원본 클래스를 사용하여 찾을 수 있습니다.
```dart
abstract class BaseClass {}
class ParentClass extends BaseClass {}
class ChildClass extends ParentClass {
bool isChild = true;
}
Get.put<BaseClass>(ParentClass());
Get.replace<BaseClass>(ChildClass());
final instance = Get.find<BaseClass>();
print(instance is ChildClass); //true
class OtherClass extends BaseClass {}
Get.lazyReplace<BaseClass>(() => OtherClass());
final instance = Get.find<BaseClass>();
print(instance is ChildClass); // false
print(instance is OtherClass); //true
```
## 메서드간의 차이점
첫째, Get.lazyPut의 `fenix`와 다른 메서드들의 `permanent`을 살펴보겠습니다.
... ...
... ... @@ -30,7 +30,7 @@ GetX는 다른 상태 관리자처럼 Streams나 ChangeNotifier를 사용하지
- _code generators에 의존하지 않음_: 당신은 어플리케이션 개발을 위한 로직을 작성하는데 개발시간의 절반을 할애했을 것입니다. 어떤 상태관리자들은 code generator에 의존하여 읽기 쉬운 코드를 작성했을 것입니다. 변수를 바꾸고 build_runner를 실행해야 하는 것은 비생산적일 수 있으며, 심지어 Flutter가 이를 반영되기를 기다리면서 커피 한 잔을 즐겨야 할 정도로 오래 기다릴 수 있습니다. GetX는 모든것을 즉각적으로 반응합니다. code generator에 의존하지 않고, 모든 면에서 당신의 생산성을 높여줍니다.
- _필요없는 context_: 아마 당신은 비즈니스 로직을 UI에 반영하기 위해, 여러 위젯 컨트롤러에 context를 넘겨주었을 것입니다. context를 이용한 위젯을 사용하기 위해, context를 다양한 클래스와 함수들을 이용하여 전달하였을 것입니다. GetX를 이용하면 그럴 필요가 없습니다. context없이 controller만으로 접근하여 사용할 수 있습니다. 말 그대로 아무 의미 없이 context를 파라미터로 넘겨줄 필요가 없습니다.
- _세분화된 컨트롤_: 대부분의 상태관리자들은 ChangeNotifier을 기반으로 동작합니다. ChangeNotifier는 notifyListeners가 호출되면 모든 위젯들에게 알릴 것입니다. 만약 당신 스크린에 수많은 ChangeNotifier 클래스를 갖는 40개의 위젯이 있다면, 한 번 업데이트 할 때마다 모든 위젯들이 다시 빌드될 것입니다. GetX를 이용하면 위젯이 중첩되더라도, 변경된 위젯만 다시 빌드됩니다. 한 Obx가 ListView를 보고있고, 다른 Obx가 ListView 안의 checkbox를 보고있을 때, checkBox 값이 변경되면, checkBox만 업데이트 되고, ListView 값이 변경되면 ListView만 업데이트 됩니다.
- _**정말** 바뀌었을 때만 재구성_: GetX는 흐름제어를 합니다. '진탁'이라는 Text를 화면에 보여준다고 해봅시다. 만약 당신이 observable 변수인 '진탁'을 다시 한 번 '진탁'으로 변경한다면, 그 위젯은 재구성되지 않습니다. 왜냐하면 GetX는 '진탁'이 이미 Text로 보여주고 있다는 것을 알고 있기 때문에, 불필요한 재구성을 하지 않습니다. 대부분(모두일 수도 있는) 지금까지의 대부분의 상태관리자들은 스크린에 다시 빌드하여 보여줍니다.
- _**정말** 바뀌었을 때만 재구성_: GetX는 흐름제어를 합니다. '진탁'이라는 Text를 화면에 보여준다고 해봅시다. 만약 당신이 obserable 변수인 '진탁'을 다시 한 번 '진탁'으로 변경한다면, 그 위젯은 재구성되지 않습니다. 왜냐하면 GetX는 '진탁'이 이미 Text로 보여주고 있다는 것을 알고 있기 때문에, 불필요한 재구성을 하지 않습니다. 대부분(모두일 수도 있는) 지금까지의 대부분의 상태관리자들은 스크린에 다시 빌드하여 보여줍니다.
## 반응형 상태 관리자
... ...
... ... @@ -59,11 +59,11 @@ var name = 'Jonatas Borges'.obs;
就这么简单!
我们把这个reactive-".obs"(ervables)变量称为 _Rx_
我们把这个reactive-".obs"(ervables)变量称为_Rx_
我们做了什么?我们创建了一个 "Stream "的 "String",分配了初始值 "Jonatas Borges",我们通知所有使用 "Jonatas Borges "的widgets,它们现在 "属于 "这个变量,当_Rx_的值发生变化时,它们也要随之改变。
这就是GetX **的** 魔力,这要归功于Dart的能力。
这就是GetX**的**魔力,这要归功于Dart的能力。
但是,我们知道,一个`Widget`只有在函数里面才能改变,因为静态类没有 "自动改变 "的能力。
... ... @@ -80,15 +80,15 @@ var name = 'Jonatas Borges'.obs;
Obx (() => Text (controller.name));
```
你只需记住 `Obx(()=>`
_你只需记住 `Obx(()=>`
你只需将Widget通过一个箭头函数传递给 `Obx()`( _Rx_ 的 "观察者")。
你只需将Widget通过一个箭头函数传递给 `Obx()`(_Rx_的 "观察者")。
`Obx`是相当聪明的,只有当`controller.name`的值发生变化时才会改变。
如果`name`是`"John"`,你把它改成了`"John"`(`name.value="John"`),因为它和之前的`value`是一样的,所以界面上不会有任何变化,而`Obx`为了节省资源,会直接忽略新的值,不重建Widget。**这是不是很神奇**
> 那么,如果我在一个`Obx`里有5个 _Rx_ (可观察的)变量呢?
> 那么,如果我在一个`Obx`里有5个_Rx_(可观察的)变量呢?
当其中**任何**一个变量发生变化时,它就会更新。
... ... @@ -96,7 +96,7 @@ Obx (() => Text (controller.name));
不会,只会更新使用那个 _Rx_ 变量的**特定 Widget**
所以,只有当 _Rx_ 变量的值发生变化时,**GetX**才会更新界面。
所以,只有当_Rx_变量的值发生变化时,**GetX**才会更新界面。
```
final isOpen = false.obs;
... ... @@ -114,13 +114,13 @@ void onButtonTap() => isOpen.value=false;
如果你需要一个**强大的**状态管理器,用**GetX**是不会错的。
它不能和变量一起工作,除了 __flows__ ,它里面的东西本质都是`Streams`
你可以将 _rxDart_ 与它结合使用,因为所有的东西都是`Streams`
你可以监听每个" _Rx_ 变量 "的 "事件"。
它不能和变量一起工作,除了__flows__,它里面的东西本质都是`Streams`
你可以将_rxDart_与它结合使用,因为所有的东西都是`Streams`
你可以监听每个"_Rx_变量 "的 "事件"。
因为里面的所有东西都是 "Streams"。
这实际上是一种 _BLoC_ 方法,比 _MobX_ 更容易,而且没有代码生成器或装饰。
你可以把**任何东西**变成一个 _"Observable"_ ,只需要在它末尾加上`.obs`
这实际上是一种_BLoC_方法,比_MobX_更容易,而且没有代码生成器或装饰。
你可以把**任何东西**变成一个_"Observable"_,只需要在它末尾加上`.obs`
### 最高性能
... ... @@ -129,8 +129,8 @@ void onButtonTap() => isOpen.value=false;
如果你的应用程序中遇到错误,并发送重复的状态变更,**GetX**将确保它不会崩溃。
使用**GetX**,只有当`value`改变时,状态才会改变。
这就是**GetX**,和使用MobX _的_ `computed`的主要区别。
当加入两个 __observable__ ,其中一个发生变化时,该 _observable_ 的监听器也会发生变化。
这就是**GetX**,和使用MobX_的_`computed`的主要区别。
当加入两个__observable__,其中一个发生变化时,该_observable_的监听器也会发生变化。
使用**GetX**,如果你连接了两个变量,`GetX()`(类似于`Observer()`)只有在它的状态真正变化时才会重建。
... ... @@ -183,13 +183,13 @@ final user = User().obs;
##### 有一个反应的状态,很容易。
我们知道, _Dart_ 现在正朝着 _null safety_ 的方向发展。
为了做好准备,从现在开始,你应该总是用一个**初始值**来开始你的 _Rx_ 变量。
我们知道,_Dart_现在正朝着_null safety_的方向发展。
为了做好准备,从现在开始,你应该总是用一个**初始值**来开始你的_Rx_变量。
> 用**GetX**将一个变量转化为一个 _observable_ + _initial value_ 是最简单,也是最实用的方法。
> 用**GetX**将一个变量转化为一个_observable_ + _initial value_是最简单,也是最实用的方法。
你只需在变量的末尾添加一个"`.obs`",即可把它变成可观察的变量,
然后它的`.value`就是 _初始值_ )。
然后它的`.value`就是_初始值_)。
### 使用视图中的值
... ... @@ -411,17 +411,17 @@ interval(count1, (_) => print("interval $_"), time: Duration(seconds: 1));
所有worker都会返回一个`Worker`实例,你可以用它来取消(通过`dispose()`)worker。
- **`ever`**
每当 _Rx_ 变量发出一个新的值时,就会被调用。
每当_Rx_变量发出一个新的值时,就会被调用。
- **`everAll`**
和 "ever "很像,但它需要一个 _Rx_ 值的 "List",每次它的变量被改变时都会被调用。就是这样。
和 "ever "很像,但它需要一个_Rx_值的 "List",每次它的变量被改变时都会被调用。就是这样。
- **`once`**
'once'只在变量第一次被改变时被调用。
- **`debounce`**
'debounce'在搜索函数中非常有用,你只希望API在用户完成输入时被调用。如果用户输入 "Jonny",你将在API中进行5次搜索,分别是字母J、o、n、n和y。使用Get不会发生这种情况,因为你将有一个 "debounce "Worker,它只会在输入结束时触发。
debounce'在搜索函数中非常有用,你只希望API在用户完成输入时被调用。如果用户输入 "Jonny",你将在API中进行5次搜索,分别是字母J、o、n、n和y。使用Get不会发生这种情况,因为你将有一个 "debounce "Worker,它只会在输入结束时触发。
- **`interval`**
'interval'与debouce不同,debouce如果用户在1秒内对一个变量进行了1000次修改,他将在规定的计时器(默认为800毫秒)后只发送最后一次修改。Interval则会忽略规定时间内的所有用户操作。如果你发送事件1分钟,每秒1000个,那么当用户停止DDOS事件时,debounce将只发送最后一个事件。建议这样做是为了避免滥用,在用户可以快速点击某样东西并获得一些好处的功能中(想象一下,用户点击某样东西可以赚取硬币,如果他在同一分钟内点击300次,他就会有300个硬币,使用间隔,你可以设置时间范围为3秒,无论是点击300次或100万次,1分钟内他最多获得20个硬币)。debounce适用于防DDOS,适用于搜索等功能,每次改变onChange都会调用你的api进行查询。Debounce会等待用户停止输入名称,进行请求。如果在上面提到的投币场景中使用它,用户只会赢得1个硬币,因为只有当用户 "暂停 "到既定时间时,它才会被执行。
... ...
... ... @@ -200,14 +200,12 @@ Bindings is the first step towards having a scalable application, you can visual
To create a Binding, simply create a class and implement Bindings
```dart
class SampleBind extends Binding {
class SampleBind extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<Controller>(() => Controller()),
Bind.lazyPut<Controller2>(() => Controller2()),
Bind.lazyPut<Controller3>(() => Controller3()),
];
void dependencies() {
Get.lazyPut<Controller>(() => Controller());
Get.lazyPut<Controller2>(() => Controller2());
Get.lazyPut<Controller3>(() => Controller3());
}
}
```
... ... @@ -489,7 +487,7 @@ class Third extends GetView<ControllerX> {
}
}
class SampleBind extends Binding {
class SampleBind extends Bindings {
@override
void dependencies() {
Get.lazyPut<ControllerX>(() => ControllerX());
... ... @@ -580,4 +578,4 @@ class SizeTransitions extends CustomTransition {
);
}
}
```
```
\ No newline at end of file
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'en_US.dart';
import 'pt_BR.dart';
import 'en_us.dart';
import 'pt_br.dart';
class TranslationService extends Translations {
static Locale? get locale => Get.deviceLocale;
static const fallbackLocale = Locale('en', 'US');
static final fallbackLocale = Locale('en', 'US');
@override
Map<String, Map<String, String>> get keys => {
'en_US': en_US,
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// void main() {
// runApp(const MyApp());
// }
// class MyApp extends StatelessWidget {
// const MyApp({Key? key}) : super(key: key);
import 'lang/translation_service.dart';
import 'routes/app_pages.dart';
import 'shared/logger/logger_utils.dart';
// @override
// Widget build(BuildContext context) {
// return GetMaterialApp(
// theme: ThemeData(useMaterial3: true),
// debugShowCheckedModeBanner: false,
// enableLog: true,
// logWriterCallback: Logger.write,
// initialRoute: AppPages.INITIAL,
// getPages: AppPages.routes,
// locale: TranslationService.locale,
// fallbackLocale: TranslationService.fallbackLocale,
// translations: TranslationService(),
// );
// }
// }
/// Nav 2 snippet
void main() {
runApp(const MyApp());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
... ... @@ -34,142 +14,116 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
getPages: [
GetPage(
participatesInRootNavigator: true,
name: '/first',
page: () => const First()),
GetPage(
name: '/second',
page: () => const Second(),
transition: Transition.downToUp,
),
GetPage(
name: '/third',
page: () => const Third(),
),
],
return GetMaterialApp.router(
debugShowCheckedModeBanner: false,
enableLog: true,
logWriterCallback: Logger.write,
// initialRoute: AppPages.INITIAL,
getPages: AppPages.routes,
locale: TranslationService.locale,
fallbackLocale: TranslationService.fallbackLocale,
translations: TranslationService(),
);
}
}
class FirstController extends GetxController {
@override
void onClose() {
print('on close first');
super.onClose();
}
}
class First extends StatelessWidget {
const First({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('First rebuild');
Get.put(FirstController());
return Scaffold(
appBar: AppBar(
title: const Text('page one'),
leading: IconButton(
icon: const Icon(Icons.more),
onPressed: () {
Get.snackbar(
'title',
"message",
mainButton:
TextButton(onPressed: () {}, child: const Text('button')),
isDismissible: true,
duration: Duration(seconds: 5),
snackbarStatus: (status) => print(status),
);
// print('THEME CHANGED');
// Get.changeTheme(
// Get.isDarkMode ? ThemeData.light() : ThemeData.dark());
},
),
),
body: Center(
child: SizedBox(
height: 300,
width: 300,
child: ElevatedButton(
onPressed: () {
Get.toNamed('/second?id=123');
},
child: const Text('next screen'),
),
),
),
);
}
}
/// Nav 2 snippet
// void main() {
// runApp(MyApp());
// }
class SecondController extends GetxController {
final textEdit = TextEditingController();
@override
void onClose() {
print('on close second');
textEdit.dispose();
super.onClose();
}
}
// class MyApp extends StatelessWidget {
// MyApp({Key? key}) : super(key: key);
class Second extends StatelessWidget {
const Second({Key? key}) : super(key: key);
// @override
// Widget build(BuildContext context) {
// return GetMaterialApp.router(
// getPages: [
// GetPage(
// participatesInRootNavigator: true,
// name: '/first',
// page: () => First()),
// GetPage(
// name: '/second',
// page: () => Second(),
// ),
// GetPage(
// name: '/third',
// page: () => Third(),
// ),
// ],
// debugShowCheckedModeBanner: false,
// );
// }
// }
@override
Widget build(BuildContext context) {
final controller = Get.put(SecondController());
print('second rebuild');
return Scaffold(
appBar: AppBar(
title: Text('page two ${Get.parameters["id"]}'),
),
body: Center(
child: Column(
children: [
Expanded(
child: TextField(
controller: controller.textEdit,
)),
SizedBox(
height: 300,
width: 300,
child: ElevatedButton(
onPressed: () {},
child: const Text('next screen'),
),
),
],
),
),
);
}
}
// class First extends StatelessWidget {
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(
// title: Text('page one'),
// leading: IconButton(
// icon: Icon(Icons.more),
// onPressed: () {
// Get.changeTheme(
// context.isDarkMode ? ThemeData.light() : ThemeData.dark());
// },
// ),
// ),
// body: Center(
// child: Container(
// height: 300,
// width: 300,
// child: ElevatedButton(
// onPressed: () {},
// child: Text('next screen'),
// ),
// ),
// ),
// );
// }
// }
class Third extends StatelessWidget {
const Third({Key? key}) : super(key: key);
// class Second extends StatelessWidget {
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(
// title: Text('page two ${Get.parameters["id"]}'),
// ),
// body: Center(
// child: Container(
// height: 300,
// width: 300,
// child: ElevatedButton(
// onPressed: () {},
// child: Text('next screen'),
// ),
// ),
// ),
// );
// }
// }
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.red,
appBar: AppBar(
title: const Text('page three'),
),
body: Center(
child: SizedBox(
height: 300,
width: 300,
child: ElevatedButton(
onPressed: () {},
child: const Text('go to first screen'),
),
),
),
);
}
}
// class Third extends StatelessWidget {
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// backgroundColor: Colors.red,
// appBar: AppBar(
// title: Text('page three'),
// ),
// body: Center(
// child: Container(
// height: 300,
// width: 300,
// child: ElevatedButton(
// onPressed: () {},
// child: Text('go to first screen'),
// ),
// ),
// ),
// );
// }
// }
... ...
import 'package:get/get.dart';
import '../data/home_api_provider.dart';
import '../data/home_repository.dart';
import '../domain/adapters/repository_adapter.dart';
import '../presentation/controllers/home_controller.dart';
class HomeBinding extends Binding {
class HomeBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<IHomeProvider>(() => HomeProvider()),
Bind.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find())),
Bind.lazyPut(() => HomeController(homeRepository: Get.find())),
];
void dependencies() {
Get.lazyPut<IHomeProvider>(() => HomeProvider());
Get.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find()));
Get.lazyPut(() => HomeController(homeRepository: Get.find()));
}
}
... ...
import 'package:get/get.dart';
import '../domain/entity/cases_model.dart';
// ignore: one_member_abstracts
... ... @@ -13,7 +12,6 @@ class HomeProvider extends GetConnect implements IHomeProvider {
httpClient.defaultDecoder =
(val) => CasesModel.fromJson(val as Map<String, dynamic>);
httpClient.baseUrl = 'https://api.covid19api.com';
super.onInit();
}
@override
... ...
... ... @@ -6,12 +6,14 @@ import 'dart:convert';
class CasesModel {
CasesModel({
required this.id,
required this.message,
required this.global,
required this.countries,
required this.date,
});
final String id;
final String message;
final Global global;
final List<Country> countries;
... ... @@ -23,17 +25,17 @@ class CasesModel {
String toRawJson() => json.encode(toJson());
factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel(
id: json["ID"] as String,
message: json["Message"] as String,
global: Global.fromJson(json["Global"] as Map<String, dynamic>),
countries: json["Countries"] == null
? []
: List<Country>.from((json["Countries"] as Iterable).map(
(x) => Country.fromJson(x as Map<String, dynamic>),
)),
countries: List<Country>.from((json["Countries"] as Iterable).map(
(x) => Country.fromJson(x as Map<String, dynamic>),
)),
date: DateTime.parse(json["Date"] as String),
);
Map<String, dynamic> toJson() => {
"ID": id,
"Message": message,
"Global": global.toJson(),
"Countries": List<dynamic>.from(countries.map((x) => x.toJson())),
... ...
... ... @@ -3,7 +3,7 @@ import 'package:get/get.dart';
import '../../domain/adapters/repository_adapter.dart';
import '../../domain/entity/cases_model.dart';
class HomeController extends StateController<CasesModel> {
class HomeController extends SuperController<CasesModel> {
HomeController({required this.homeRepository});
final IHomeRepository homeRepository;
... ... @@ -11,12 +11,74 @@ class HomeController extends StateController<CasesModel> {
@override
void onInit() {
super.onInit();
//Loading, Success, Error handle with 1 line of code
futurize(homeRepository.getCases);
append(() => homeRepository.getCases);
}
Country getCountryById(String id) {
final index = int.tryParse(id);
return index != null ? state.countries[index] : state.countries.first;
if (index != null) {
return state!.countries[index];
}
return state!.countries.first;
}
@override
void onReady() {
print('The build method is done. '
'Your controller is ready to call dialogs and snackbars');
super.onReady();
}
@override
void onClose() {
print('onClose called');
super.onClose();
}
@override
void didChangeMetrics() {
print('the window size did change');
super.didChangeMetrics();
}
@override
void didChangePlatformBrightness() {
print('platform change ThemeMode');
super.didChangePlatformBrightness();
}
@override
Future<bool> didPushRoute(String route) {
print('the route $route will be open');
return super.didPushRoute(route);
}
@override
Future<bool> didPopRoute() {
print('the current route will be closed');
return super.didPopRoute();
}
@override
void onDetached() {
print('onDetached called');
}
@override
void onInactive() {
print('onInative called');
}
@override
void onPaused() {
print('onPaused called');
}
@override
void onResumed() {
print('onResumed called');
}
}
... ...
... ... @@ -6,11 +6,10 @@ import 'package:get/get.dart';
import '../controllers/home_controller.dart';
class CountryView extends GetView<HomeController> {
const CountryView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
colorFilter: ColorFilter.linearToSrgbGamma(),
... ... @@ -18,36 +17,37 @@ class CountryView extends GetView<HomeController> {
"https://images.pexels.com/photos/3902882/pexels-photo-3902882.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"))),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text('corona_by_country'.tr),
child: Container(
child: Scaffold(
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
),
body: Center(
child: ListView.builder(
itemCount: controller.state.countries.length,
itemBuilder: (context, index) {
final country = controller.state.countries[index];
return ListTile(
onTap: () async {
//Get.rootDelegate.toNamed('/home/country');
final data =
await Get.toNamed('/home/country/details?id=$index');
Get.log(data);
},
trailing: CircleAvatar(
backgroundImage: NetworkImage(
"https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),
),
title: Text(country.country),
subtitle: Text(
// ignore: lines_longer_than_80_chars
'${'total_infecteds'.tr}${' ${country.totalConfirmed}'}'),
);
}),
appBar: AppBar(
title: Text('corona_by_country'.tr),
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
),
body: Center(
child: ListView.builder(
itemCount: controller.state!.countries.length,
itemBuilder: (context, index) {
final country = controller.state!.countries[index];
return ListTile(
onTap: () {
//Get.rootDelegate.toNamed('/home/country');
Get.rootDelegate
.toNamed('/home/country/details?id=$index');
},
trailing: CircleAvatar(
backgroundImage: NetworkImage(
"https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),
),
title: Text(country.country),
subtitle: Text(
// ignore: lines_longer_than_80_chars
'${'total_infecteds'.tr}${' ${country.totalConfirmed}'}'),
);
}),
),
),
),
),
... ...
... ... @@ -2,92 +2,83 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
class DetailsView extends GetView<HomeController> {
const DetailsView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final parameter = context.params; //Get.parameters;
final parameter = Get.rootDelegate.parameters;
final country = controller.getCountryById(parameter['id'] ?? '');
return Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
colorFilter: const ColorFilter.linearToSrgbGamma(),
colorFilter: ColorFilter.linearToSrgbGamma(),
image: NetworkImage(
"https://flagpedia.net/data/flags/normal/${country.countryCode.toLowerCase()}.png"),
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text('details'.tr),
backgroundColor: Colors.black12,
elevation: 0,
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
country.country,
style:
const TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 35,
),
Text(
'total_confirmed'.tr,
style: const TextStyle(
fontSize: 25,
child: Container(
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text('details'.tr),
backgroundColor: Colors.black12,
elevation: 0,
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${country.country}',
style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
),
SizedBox(
height: 35,
),
Text(
'total_confirmed'.tr,
style: TextStyle(
fontSize: 25,
),
),
Text(
'${country.totalConfirmed}',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
),
Text(
'${country.totalConfirmed}',
style:
const TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 10,
),
Text(
'total_deaths'.tr,
style: const TextStyle(
fontSize: 25,
SizedBox(
height: 10,
),
),
Text(
'${country.totalDeaths}',
style:
const TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 10,
),
Text(
'total_recovered'.tr,
style: const TextStyle(
fontSize: 25,
Text(
'total_deaths'.tr,
style: TextStyle(
fontSize: 25,
),
),
),
Text(
'${country.totalRecovered}',
style:
const TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
TextButton(
onPressed: () {
Get.back(result: 'djsoidjsoidj');
},
child: const Text('back'))
],
)),
Text(
'${country.totalDeaths}',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
'total_recovered'.tr,
style: TextStyle(
fontSize: 25,
),
),
Text(
'${country.totalRecovered}',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
],
)),
),
),
),
);
... ...
... ... @@ -4,12 +4,10 @@ import 'package:get/get.dart';
import '../controllers/home_controller.dart';
class HomeView extends GetView<HomeController> {
const HomeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
decoration: BoxDecoration(
color: Colors.white,
image: DecorationImage(
fit: BoxFit.cover,
... ... @@ -22,7 +20,7 @@ class HomeView extends GetView<HomeController> {
backgroundColor: Colors.transparent,
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.add),
icon: Icon(Icons.add),
onPressed: () {
Get.snackbar('title', 'message');
},
... ... @@ -38,53 +36,52 @@ class HomeView extends GetView<HomeController> {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
SizedBox(
height: 100,
),
Text(
'total_confirmed'.tr,
style: const TextStyle(
style: TextStyle(
fontSize: 30,
),
),
Text(
'${state!.global.totalConfirmed}',
style: const TextStyle(
fontSize: 45, fontWeight: FontWeight.bold),
style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
),
const SizedBox(
SizedBox(
height: 10,
),
Text(
'total_deaths'.tr,
style: const TextStyle(
style: TextStyle(
fontSize: 30,
),
),
Text(
'${state.global.totalDeaths}',
style: const TextStyle(
fontSize: 45, fontWeight: FontWeight.bold),
style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
),
const SizedBox(
SizedBox(
height: 10,
),
OutlinedButton(
style: OutlinedButton.styleFrom(
textStyle: const TextStyle(color: Colors.black),
side: const BorderSide(
textStyle: TextStyle(color: Colors.black),
side: BorderSide(
color: Colors.deepPurple,
width: 3,
),
shape: const StadiumBorder(),
shape: StadiumBorder(),
),
onPressed: () async {
//await Navigation Get.rootDelegate.toNamed('/home/country');
Get.toNamed('/home/country');
final data =
await Get.rootDelegate.toNamed('/home/country');
print('DATA: $data');
},
child: Text(
'fetch_country'.tr,
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
),
... ... @@ -92,17 +89,17 @@ class HomeView extends GetView<HomeController> {
),
OutlinedButton(
style: OutlinedButton.styleFrom(
textStyle: const TextStyle(color: Colors.black),
side: const BorderSide(
textStyle: TextStyle(color: Colors.black),
side: BorderSide(
color: Colors.deepPurple,
width: 3,
),
shape: const StadiumBorder(),
shape: StadiumBorder(),
),
onPressed: () {
Get.updateLocale(const Locale('pt', 'BR'));
Get.updateLocale(Locale('pt', 'BR'));
},
child: const Text(
child: Text(
'Update language to Portuguese',
style: TextStyle(
fontWeight: FontWeight.bold,
... ...
... ... @@ -13,21 +13,20 @@ class AppPages {
static final routes = [
GetPage(
name: Routes.HOME,
page: () => const HomeView(),
binding: HomeBinding(),
children: [
GetPage(
name: Routes.COUNTRY,
page: () => const CountryView(),
children: [
GetPage(
name: Routes.DETAILS,
page: () => const DetailsView(),
),
],
),
],
),
name: Routes.HOME,
page: () => HomeView(),
binding: HomeBinding(),
children: [
GetPage(
name: Routes.COUNTRY,
page: () => CountryView(),
children: [
GetPage(
name: Routes.DETAILS,
page: () => DetailsView(),
),
],
),
]),
];
}
... ...
... ... @@ -4,8 +4,4 @@ abstract class Routes {
static const HOME = '/home';
static const COUNTRY = '/country';
static const DETAILS = '/details';
static const DASHBOARD = '/dashboard';
static const PROFILE = '/profile';
static const PRODUCTS = '/products';
}
... ...
mixin Logger {
// Sample of abstract logging function
static void write(String text, {bool isError = false}) {
// ignore: avoid_print
Future.microtask(() => print('** $text. isError: [$isError]'));
}
}
... ...
... ... @@ -18,11 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=3.0.1 <4.0.0"
dependency_overrides:
get:
path: ../
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
... ... @@ -37,8 +33,6 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
get_test: 4.0.1
flutter_lints: ^2.0.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
... ... @@ -75,4 +69,4 @@ flutter:
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
# see https://flutter.dev/custom-fonts/#from-packages
\ No newline at end of file
... ...
import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
... ... @@ -8,57 +8,61 @@ import 'package:get_demo/pages/home/domain/entity/cases_model.dart';
import 'package:get_demo/pages/home/presentation/controllers/home_controller.dart';
// import 'package:get_demo/routes/app_pages.dart';
// import 'package:get_test/get_test.dart';
import 'package:matcher/matcher.dart' as m;
class MockRepositorySuccess implements IHomeRepository {
class MockRepository implements IHomeRepository {
@override
Future<CasesModel> getCases() async {
return CasesModel(
global: Global(
totalDeaths: 100,
totalConfirmed: 200,
date: DateTime.now(),
newConfirmed: 0,
newDeaths: 0,
newRecovered: 0,
totalRecovered: 0),
countries: [],
date: DateTime.now(),
message: '',
);
}
}
await Future.delayed(Duration(milliseconds: 100));
if (Random().nextBool()) {
return CasesModel(
global: Global(
totalDeaths: 100,
totalConfirmed: 200,
date: DateTime.now(),
newConfirmed: 0,
newDeaths: 0,
newRecovered: 0,
totalRecovered: 0),
countries: [],
date: DateTime.now(),
id: '',
message: '',
);
}
class MockRepositoryFailure implements IHomeRepository {
@override
Future<CasesModel> getCases() async {
return Future<CasesModel>.error('error');
}
}
class MockBinding extends Binding {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<IHomeRepository>(() => MockRepositorySuccess()),
Bind.lazyPut<HomeController>(
() => HomeController(homeRepository: Get.find()),
)
];
}
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
setUpAll(() => HttpOverrides.global = null);
final binding = MockBinding();
final binding = BindingsBuilder(() {
Get.lazyPut<IHomeRepository>(() => MockRepository());
Get.lazyPut<HomeController>(
() => HomeController(homeRepository: Get.find()));
});
test('Test Binding', () {
expect(Get.isPrepared<HomeController>(), false);
expect(Get.isPrepared<IHomeRepository>(), false);
/// test you Binding class with BindingsBuilder
binding.builder();
expect(Get.isPrepared<HomeController>(), true);
expect(Get.isPrepared<IHomeRepository>(), true);
Get.reset();
});
test('Test Controller', () async {
/// Controller can't be on memory
expect(() => Get.find<HomeController>(tag: 'success'),
throwsA(const TypeMatcher<String>()));
expect(() => Get.find<HomeController>(), throwsA(m.TypeMatcher<String>()));
/// binding will put the controller on memory
binding.dependencies();
/// build Binding
binding.builder();
/// recover your controller
final controller = Get.find<HomeController>();
... ... @@ -70,17 +74,26 @@ void main() {
expect(controller.status.isLoading, true);
/// await time request
await Future.delayed(const Duration(milliseconds: 100));
await Future.delayed(Duration(milliseconds: 100));
/// test if status is success
expect(controller.status.isSuccess, true);
expect(controller.state.global.totalDeaths, 100);
expect(controller.state.global.totalConfirmed, 200);
if (controller.status.isError) {
expect(controller.state, null);
}
/// test if status is error
Get.lazyReplace<IHomeRepository>(() => MockRepositoryFailure());
expect(controller.status.isError, true);
expect(controller.state, null);
if (controller.status.isSuccess) {
expect(controller.state!.global.totalDeaths, 100);
expect(controller.state!.global.totalConfirmed, 200);
}
});
test('ever', () async {
final count = ''.obs;
var result = '';
ever<String>(count, (value) {
result = value;
});
count.value = '1';
expect('1', result);
});
/// Tests with GetTests
... ... @@ -137,3 +150,26 @@ void main() {
},
);*/
}
class Controller extends GetxController {
final count = 0.obs;
void increment() => count.value++;
@override
void onInit() {
print('inittt');
super.onInit();
}
@override
void onReady() {
print('onReady');
super.onReady();
}
@override
void onClose() {
super.onClose();
print('onClose');
}
}
... ...
... ... @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>8.0</string>
</dict>
</plist>
... ...
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/jonatasborges/flutter
FLUTTER_APPLICATION_PATH=/Users/jonatasborges/getx5/getx/example_nav2
FLUTTER_APPLICATION_PATH=/Users/jonatasborges/Downloads/get-4.6.1/example_nav2
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=/Users/jonatasborges/getx5/getx/example_nav2/lib/main.dart
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iOGQzNTgxMGU5MWFiOGZjMzliYTVlN2E0MWJmZjZmNjk3ZThlM2E4Lw==
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TRACK_WIDGET_CREATION=false
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=/Users/jonatasborges/getx5/getx/example_nav2/.dart_tool/package_config.json
PACKAGE_CONFIG=.packages
... ...
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/jonatasborges/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/jonatasborges/getx5/getx/example_nav2"
export "FLUTTER_APPLICATION_PATH=/Users/jonatasborges/Downloads/get-4.6.1/example_nav2"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=/Users/jonatasborges/getx5/getx/example_nav2/lib/main.dart"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC9iOGQzNTgxMGU5MWFiOGZjMzliYTVlN2E0MWJmZjZmNjk3ZThlM2E4Lw=="
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=/Users/jonatasborges/getx5/getx/example_nav2/.dart_tool/package_config.json"
export "PACKAGE_CONFIG=.packages"
... ...
... ... @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
... ... @@ -127,7 +127,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
... ... @@ -171,12 +171,10 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
... ... @@ -187,7 +185,6 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
... ... @@ -275,7 +272,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
... ... @@ -349,7 +346,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
... ... @@ -398,7 +395,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
... ...
... ... @@ -41,9 +41,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
... ...
... ... @@ -5,14 +5,14 @@ import '../routes/app_pages.dart';
class EnsureAuthMiddleware extends GetMiddleware {
@override
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async {
// you can do whatever you want here
// but it's preferable to make this method fast
// await Future.delayed(Duration(milliseconds: 500));
if (!AuthService.to.isLoggedInValue) {
final newRoute = Routes.LOGIN_THEN(route.pageSettings!.name);
return RouteDecoder.fromRoute(newRoute);
final newRoute = Routes.LOGIN_THEN(route.location!);
return GetNavConfig.fromRoute(newRoute);
}
return await super.redirectDelegate(route);
}
... ... @@ -20,13 +20,13 @@ class EnsureAuthMiddleware extends GetMiddleware {
class EnsureNotAuthedMiddleware extends GetMiddleware {
@override
Future<RouteDecoder?> redirectDelegate(RouteDecoder route) async {
Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async {
if (AuthService.to.isLoggedInValue) {
//NEVER navigate to auth screen, when user is already authed
return null;
//OR redirect user to another screen
//return RouteDecoder.fromRoute(Routes.PROFILE);
//return GetNavConfig.fromRoute(Routes.PROFILE);
}
return await super.redirectDelegate(route);
}
... ...
... ... @@ -2,13 +2,11 @@ import 'package:get/get.dart';
import '../controllers/dashboard_controller.dart';
class DashboardBinding extends Binding {
class DashboardBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<DashboardController>(
() => DashboardController(),
)
];
void dependencies() {
Get.lazyPut<DashboardController>(
() => DashboardController(),
);
}
}
... ...
... ... @@ -8,7 +8,7 @@ class DashboardController extends GetxController {
void onReady() {
super.onReady();
Timer.periodic(
const Duration(seconds: 1),
Duration(seconds: 1),
(timer) {
now.value = DateTime.now();
},
... ...
... ... @@ -4,8 +4,6 @@ import 'package:get/get.dart';
import '../controllers/dashboard_controller.dart';
class DashboardView extends GetView<DashboardController> {
const DashboardView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
... ... @@ -14,7 +12,7 @@ class DashboardView extends GetView<DashboardController> {
() => Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
Text(
'DashboardView is working',
style: TextStyle(fontSize: 20),
),
... ...
... ... @@ -2,13 +2,11 @@ import 'package:get/get.dart';
import '../controllers/home_controller.dart';
class HomeBinding extends Binding {
class HomeBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<HomeController>(
() => HomeController(),
)
];
void dependencies() {
Get.lazyPut<HomeController>(
() => HomeController(),
);
}
}
... ...
... ... @@ -5,61 +5,61 @@ import '../../../routes/app_pages.dart';
import '../controllers/home_controller.dart';
class HomeView extends GetView<HomeController> {
const HomeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
color: Colors.yellow,
width: double.infinity,
height: 25,
),
Expanded(
child: GetRouterOutlet.builder(
route: Routes.home,
builder: (context) {
return Scaffold(
body: GetRouterOutlet(
initialRoute: Routes.dashboard,
anchorRoute: Routes.home,
),
bottomNavigationBar: IndexedRouteBuilder(
routes: const [
Routes.dashboard,
Routes.profile,
Routes.products
],
builder: (context, routes, index) {
final delegate = context.delegate;
return BottomNavigationBar(
currentIndex: index,
onTap: (value) => delegate.toNamed(routes[value]),
items: const [
// _Paths.HOME + [Empty]
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
// _Paths.HOME + Routes.PROFILE
BottomNavigationBarItem(
icon: Icon(Icons.account_box_rounded),
label: 'Profile',
),
// _Paths.HOME + _Paths.PRODUCTS
BottomNavigationBarItem(
icon: Icon(Icons.account_box_rounded),
label: 'Products',
),
],
);
}),
);
return GetRouterOutlet.builder(
builder: (context, delegate, currentRoute) {
//This router outlet handles the appbar and the bottom navigation bar
final currentLocation = currentRoute?.location;
var currentIndex = 0;
if (currentLocation?.startsWith(Routes.PRODUCTS) == true) {
currentIndex = 2;
}
if (currentLocation?.startsWith(Routes.PROFILE) == true) {
currentIndex = 1;
}
return Scaffold(
body: GetRouterOutlet(
initialRoute: Routes.DASHBOARD,
// anchorRoute: Routes.HOME,
key: Get.nestedKey(Routes.HOME),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (value) {
switch (value) {
case 0:
delegate.toNamed(Routes.HOME);
break;
case 1:
delegate.toNamed(Routes.PROFILE);
break;
case 2:
delegate.toNamed(Routes.PRODUCTS);
break;
default:
}
},
items: [
// _Paths.HOME + [Empty]
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
// _Paths.HOME + Routes.PROFILE
BottomNavigationBarItem(
icon: Icon(Icons.account_box_rounded),
label: 'Profile',
),
// _Paths.HOME + _Paths.PRODUCTS
BottomNavigationBarItem(
icon: Icon(Icons.account_box_rounded),
label: 'Products',
),
],
),
),
],
);
},
);
}
}
... ...
... ... @@ -2,11 +2,11 @@ import 'package:get/get.dart';
import '../controllers/login_controller.dart';
class LoginBinding extends Binding {
class LoginBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut(() => LoginController()),
];
void dependencies() {
Get.lazyPut<LoginController>(
() => LoginController(),
);
}
}
... ...
... ... @@ -6,8 +6,6 @@ import '../../../routes/app_pages.dart';
import '../controllers/login_controller.dart';
class LoginView extends GetView<LoginController> {
const LoginView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
... ... @@ -27,14 +25,15 @@ class LoginView extends GetView<LoginController> {
},
),
MaterialButton(
child: const Text(
child: Text(
'Do LOGIN !!',
style: TextStyle(color: Colors.blue, fontSize: 20),
),
onPressed: () {
AuthService.to.login();
final thenTo = context.params['then'];
Get.offNamed(thenTo ?? Routes.home);
final thenTo = Get.rootDelegate.currentConfiguration!
.currentPage!.parameters?['then'];
Get.rootDelegate.offNamed(thenTo ?? Routes.HOME);
},
),
],
... ...
... ... @@ -2,15 +2,13 @@ import 'package:get/get.dart';
import '../controllers/product_details_controller.dart';
class ProductDetailsBinding extends Binding {
class ProductDetailsBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.spawn<ProductDetailsController>(
() => ProductDetailsController(
Get.parameters['productId'] ?? '',
),
)
];
void dependencies() {
Get.create<ProductDetailsController>(
() => ProductDetailsController(
Get.parameters['productId'] ?? '',
),
);
}
}
... ...
... ... @@ -13,7 +13,6 @@ class ProductDetailsController extends GetxController {
@override
void onClose() {
Get.log('ProductDetailsController close with id: $productId');
super.onClose();
}
}
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/product_details_controller.dart';
class ProductDetailsView extends GetWidget<ProductDetailsController> {
const ProductDetailsView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
... ... @@ -13,7 +12,7 @@ class ProductDetailsView extends GetWidget<ProductDetailsController> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
Text(
'ProductDetailsView is working',
style: TextStyle(fontSize: 20),
),
... ...
... ... @@ -2,13 +2,11 @@ import 'package:get/get.dart';
import '../controllers/products_controller.dart';
class ProductsBinding extends Binding {
class ProductsBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<ProductsController>(
() => ProductsController(),
)
];
void dependencies() {
Get.lazyPut<ProductsController>(
() => ProductsController(),
);
}
}
... ...
... ... @@ -5,19 +5,18 @@ import '../../../routes/app_pages.dart';
import '../controllers/products_controller.dart';
class ProductsView extends GetView<ProductsController> {
const ProductsView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton.extended(
onPressed: () => controller.loadDemoProductsFromSomeWhere(),
label: const Text('Add'),
onPressed: controller.loadDemoProductsFromSomeWhere,
label: Text('Add'),
),
body: Column(
children: [
const Hero(
Hero(
tag: 'heroLogo',
child: FlutterLogo(),
child: const FlutterLogo(),
),
Expanded(
child: Obx(
... ... @@ -32,7 +31,8 @@ class ProductsView extends GetView<ProductsController> {
final item = controller.products[index];
return ListTile(
onTap: () {
Get.toNamed(Routes.PRODUCT_DETAILS(item.id));
Get.rootDelegate
.toNamed(Routes.PRODUCT_DETAILS(item.id));
},
title: Text(item.name),
subtitle: Text(item.id),
... ...
... ... @@ -2,13 +2,11 @@ import 'package:get/get.dart';
import '../controllers/profile_controller.dart';
class ProfileBinding extends Binding {
class ProfileBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<ProfileController>(
() => ProfileController(),
)
];
void dependencies() {
Get.lazyPut<ProfileController>(
() => ProfileController(),
);
}
}
... ...
... ... @@ -5,8 +5,6 @@ import '../../../routes/app_pages.dart';
import '../controllers/profile_controller.dart';
class ProfileView extends GetView<ProfileController> {
const ProfileView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
... ... @@ -15,16 +13,16 @@ class ProfileView extends GetView<ProfileController> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
Text(
'ProfileView is working',
style: TextStyle(fontSize: 20),
),
const Hero(
Hero(
tag: 'heroLogo',
child: FlutterLogo(),
child: const FlutterLogo(),
),
MaterialButton(
child: const Text('Show a test dialog'),
child: Text('Show a test dialog'),
onPressed: () {
//shows a dialog
Get.defaultDialog(
... ... @@ -34,14 +32,14 @@ class ProfileView extends GetView<ProfileController> {
},
),
MaterialButton(
child: const Text('Show a test dialog in Home router outlet'),
child: Text('Show a test dialog in Home router outlet'),
onPressed: () {
//shows a dialog
Get.defaultDialog(
title: 'Test Dialog In Home Outlet !!',
barrierDismissible: true,
id: Routes.home,
// navigatorKey: Get.nestedKey(Routes.HOME),
navigatorKey: Get.nestedKey(Routes.HOME),
);
},
)
... ...
... ... @@ -2,13 +2,11 @@ import 'package:get/get.dart';
import '../controllers/root_controller.dart';
class RootBinding extends Binding {
class RootBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<RootController>(
() => RootController(),
)
];
void dependencies() {
Get.lazyPut<RootController>(
() => RootController(),
);
}
}
... ...
import 'package:get/get.dart';
class RootController extends GetxController {
//TODO: Implement RootController
final count = 0.obs;
@override
void onInit() {
... ... @@ -8,6 +10,11 @@ class RootController extends GetxController {
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {}
void increment() => count.value++;
}
... ...
... ... @@ -19,18 +19,18 @@ class DrawerWidget extends StatelessWidget {
color: Colors.red,
),
ListTile(
title: const Text('Home'),
title: Text('Home'),
onTap: () {
Get.toNamed(Routes.home);
Get.rootDelegate.toNamed(Routes.HOME);
//to close the drawer
Navigator.of(context).pop();
},
),
ListTile(
title: const Text('Settings'),
title: Text('Settings'),
onTap: () {
Get.toNamed(Routes.settings);
Get.rootDelegate.toNamed(Routes.SETTINGS);
//to close the drawer
Navigator.of(context).pop();
... ... @@ -38,7 +38,7 @@ class DrawerWidget extends StatelessWidget {
),
if (AuthService.to.isLoggedInValue)
ListTile(
title: const Text(
title: Text(
'Logout',
style: TextStyle(
color: Colors.red,
... ... @@ -46,7 +46,7 @@ class DrawerWidget extends StatelessWidget {
),
onTap: () {
AuthService.to.logout();
Get.toNamed(Routes.login);
Get.rootDelegate.toNamed(Routes.LOGIN);
//to close the drawer
Navigator.of(context).pop();
... ... @@ -54,14 +54,14 @@ class DrawerWidget extends StatelessWidget {
),
if (!AuthService.to.isLoggedInValue)
ListTile(
title: const Text(
title: Text(
'Login',
style: TextStyle(
color: Colors.blue,
),
),
onTap: () {
Get.toNamed(Routes.login);
Get.rootDelegate.toNamed(Routes.LOGIN);
//to close the drawer
Navigator.of(context).pop();
... ...
... ... @@ -6,25 +6,26 @@ import '../controllers/root_controller.dart';
import 'drawer.dart';
class RootView extends GetView<RootController> {
const RootView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: const DrawerWidget(),
appBar: AppBar(
title: RouterListener(builder: (context) {
final title = context.location;
return Text(title);
}),
centerTitle: true,
),
//body: HomeView(),
body: GetRouterOutlet(
initialRoute: Routes.home,
anchorRoute: '/',
),
return GetRouterOutlet.builder(
builder: (context, delegate, current) {
final title = current?.location;
return Scaffold(
drawer: DrawerWidget(),
appBar: AppBar(
title: Text(title ?? ''),
centerTitle: true,
),
body: GetRouterOutlet(
initialRoute: Routes.HOME,
// anchorRoute: '/',
// filterPages: (afterAnchor) {
// return afterAnchor.take(1);
// },
),
);
},
);
}
}
... ...
... ... @@ -2,13 +2,11 @@ import 'package:get/get.dart';
import '../controllers/settings_controller.dart';
class SettingsBinding extends Binding {
class SettingsBinding extends Bindings {
@override
List<Bind> dependencies() {
return [
Bind.lazyPut<SettingsController>(
() => SettingsController(),
)
];
void dependencies() {
Get.lazyPut<SettingsController>(
() => SettingsController(),
);
}
}
... ...
import 'package:get/get.dart';
class SettingsController extends GetxController {
//TODO: Implement SettingsController
final count = 0.obs;
@override
void onInit() {
... ... @@ -8,6 +10,11 @@ class SettingsController extends GetxController {
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {}
void increment() => count.value++;
}
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/settings_controller.dart';
class SettingsView extends GetView<SettingsController> {
const SettingsView({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
return Scaffold(
body: Center(
child: Text(
'SettingsView is working',
... ...
... ... @@ -23,13 +23,13 @@ part 'app_routes.dart';
class AppPages {
AppPages._();
static const initial = Routes.home;
static const INITIAL = Routes.HOME;
static final routes = [
GetPage(
name: '/',
page: () => const RootView(),
bindings: [RootBinding()],
page: () => RootView(),
binding: RootBinding(),
participatesInRootNavigator: true,
preventDuplicates: true,
children: [
... ... @@ -38,52 +38,46 @@ class AppPages {
//only enter this route when not authed
EnsureNotAuthedMiddleware(),
],
name: _Paths.login,
page: () => const LoginView(),
bindings: [LoginBinding()],
name: _Paths.LOGIN,
page: () => LoginView(),
binding: LoginBinding(),
),
GetPage(
preventDuplicates: true,
name: _Paths.home,
page: () => const HomeView(),
name: _Paths.HOME,
page: () => HomeView(),
bindings: [
HomeBinding(),
],
title: null,
children: [
GetPage(
name: _Paths.dashboard,
page: () => const DashboardView(),
bindings: [
DashboardBinding(),
],
name: _Paths.DASHBOARD,
page: () => DashboardView(),
binding: DashboardBinding(),
),
GetPage(
middlewares: [
//only enter this route when authed
EnsureAuthMiddleware(),
],
name: _Paths.profile,
page: () => const ProfileView(),
name: _Paths.PROFILE,
page: () => ProfileView(),
title: 'Profile',
transition: Transition.size,
bindings: [ProfileBinding()],
binding: ProfileBinding(),
),
GetPage(
name: _Paths.products,
page: () => const ProductsView(),
name: _Paths.PRODUCTS,
page: () => ProductsView(),
title: 'Products',
transition: Transition.cupertino,
showCupertinoParallax: true,
participatesInRootNavigator: false,
bindings: [ProductsBinding(), ProductDetailsBinding()],
transition: Transition.zoom,
binding: ProductsBinding(),
children: [
GetPage(
name: _Paths.productDetails,
transition: Transition.cupertino,
showCupertinoParallax: true,
page: () => const ProductDetailsView(),
bindings: const [],
name: _Paths.PRODUCT_DETAILS,
page: () => ProductDetailsView(),
binding: ProductDetailsBinding(),
middlewares: [
//only enter this route when authed
EnsureAuthMiddleware(),
... ... @@ -94,11 +88,9 @@ class AppPages {
],
),
GetPage(
name: _Paths.settings,
page: () => const SettingsView(),
bindings: [
SettingsBinding(),
],
name: _Paths.SETTINGS,
page: () => SettingsView(),
binding: SettingsBinding(),
),
],
),
... ...
... ... @@ -4,27 +4,27 @@ part of 'app_pages.dart';
// DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart
abstract class Routes {
static const home = _Paths.home;
static const HOME = _Paths.HOME;
static const profile = _Paths.home + _Paths.profile;
static const settings = _Paths.settings;
static const PROFILE = _Paths.HOME + _Paths.PROFILE;
static const SETTINGS = _Paths.SETTINGS;
static const products = _Paths.home + _Paths.products;
static const PRODUCTS = _Paths.HOME + _Paths.PRODUCTS;
static const login = _Paths.login;
static const dashboard = _Paths.home + _Paths.dashboard;
static const LOGIN = _Paths.LOGIN;
static const DASHBOARD = _Paths.HOME + _Paths.DASHBOARD;
Routes._();
static String LOGIN_THEN(String afterSuccessfulLogin) =>
'$login?then=${Uri.encodeQueryComponent(afterSuccessfulLogin)}';
static String PRODUCT_DETAILS(String productId) => '$products/$productId';
'$LOGIN?then=${Uri.encodeQueryComponent(afterSuccessfulLogin)}';
static String PRODUCT_DETAILS(String productId) => '$PRODUCTS/$productId';
}
abstract class _Paths {
static const home = '/home';
static const products = '/products';
static const profile = '/profile';
static const settings = '/settings';
static const productDetails = '/:productId';
static const login = '/login';
static const dashboard = '/dashboard';
static const HOME = '/home';
static const PRODUCTS = '/products';
static const PROFILE = '/profile';
static const SETTINGS = '/settings';
static const PRODUCT_DETAILS = '/:productId';
static const LOGIN = '/login';
static const DASHBOARD = '/dashboard';
}
... ...
import 'package:example_nav2/services/auth_service.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'app/routes/app_pages.dart';
import 'services/auth_service.dart';
void main() {
runApp(
GetMaterialApp(
GetMaterialApp.router(
title: "Application",
binds: [
Bind.put(AuthService()),
],
initialBinding: BindingsBuilder(
() {
Get.put(AuthService());
},
),
getPages: AppPages.routes,
initialRoute: AppPages.initial,
// builder: (context, child) {
// return FutureBuilder<void>(
// key: ValueKey('initFuture'),
// future: Get.find<SplashService>().init(),
// builder: (context, snapshot) {
// if (snapshot.connectionState == ConnectionState.done) {
// return child ?? SizedBox.shrink();
// }
// return SplashView();
// },
// );
// },
// routeInformationParser: GetInformationParser(
// // initialRoute: Routes.HOME,
// ),
... ...
... ... @@ -3,16 +3,16 @@ version: 1.0.0+1
publish_to: none
description: A new Flutter project.
environment:
sdk: ">=2.19.2 <3.0.0"
sdk: ">=2.12.0 <3.0.0"
dependencies:
cupertino_icons: ^1.0.2
effective_dart: 1.3.1
# get: ^4.1.4
get:
path: ../
flutter:
sdk: flutter
flutter_lints: ^2.0.1
dev_dependencies:
flutter_test:
... ...
... ... @@ -5,9 +5,6 @@
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
... ... @@ -16,8 +13,3 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST})
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
... ...
/// GetX is an extra-light and powerful multi-platform framework.
/// GetX is an extra-light and powerful multiplatform framework.
/// It combines high performance state management, intelligent dependency
/// injection, and route management in a quick and practical way.
library get;
export 'get_animations/index.dart';
export 'get_common/get_reset.dart';
export 'get_connect/connect.dart';
export 'get_core/get_core.dart';
... ...
import '../get.dart';
extension GetResetExt on GetInterface {
void reset({bool clearRouteBindings = true}) {
Get.resetInstance(clearRouteBindings: clearRouteBindings);
// Get.clearRouteTree();
void reset(
{@deprecated bool clearFactory = true, bool clearRouteBindings = true}) {
GetInstance().resetInstance(clearRouteBindings: clearRouteBindings);
Get.clearRouteTree();
Get.clearTranslations();
// Get.resetRootNavigator();
Get.resetRootNavigator();
}
}
... ...
... ... @@ -12,7 +12,7 @@ export 'http/src/multipart/multipart_file.dart';
export 'http/src/response/response.dart';
export 'sockets/sockets.dart';
abstract class GetConnectInterface with GetLifeCycleMixin {
abstract class GetConnectInterface with GetLifeCycleBase {
List<GetSocket>? sockets;
GetHttpClient get httpClient;
... ... @@ -100,7 +100,9 @@ class GetConnect extends GetConnectInterface {
this.maxAuthRetries = 1,
this.allowAutoSignedCert = false,
this.withCredentials = false,
});
}) {
$configureLifeCycle();
}
bool allowAutoSignedCert;
String userAgent;
... ... @@ -278,7 +280,7 @@ class GetConnect extends GetConnectInterface {
return baseUrl == null ? url : baseUrl! + url;
}
/// query allow made GraphQL raw queries
/// query allow made GraphQL raw querys
/// final connect = GetConnect();
/// connect.baseUrl = 'https://countries.trevorblades.com/';
/// final response = await connect.query(
... ... @@ -316,20 +318,17 @@ class GetConnect extends GetConnectInterface {
return GraphQLResponse<T>(
graphQLErrors: listError
.map((e) => GraphQLError(
code: (e['extensions'] != null
? e['extensions']['code'] ?? ''
: '')
.toString(),
message: (e['message'] ?? '').toString(),
code: e['extensions']['code']?.toString(),
message: e['message']?.toString(),
))
.toList());
}
return GraphQLResponse<T>.fromResponse(res);
} on Exception catch (err) {
} on Exception catch (_) {
return GraphQLResponse<T>(graphQLErrors: [
GraphQLError(
code: null,
message: err.toString(),
message: _.toString(),
)
]);
}
... ... @@ -360,11 +359,11 @@ class GetConnect extends GetConnectInterface {
.toList());
}
return GraphQLResponse<T>.fromResponse(res);
} on Exception catch (err) {
} on Exception catch (_) {
return GraphQLResponse<T>(graphQLErrors: [
GraphQLError(
code: null,
message: err.toString(),
message: _.toString(),
)
]);
}
... ...
List<int> fileToBytes(dynamic data) {
if (data is List<int>) {
return data;
} else {
throw const FormatException(
'File is not "File" or "String" or "List<int>"');
}
}
// void writeOnFile(List<int> bytes) {
// var blob = html.Blob(["data"], 'text/plain', 'native');
// var anchorElement = html.AnchorElement(
// href: html.Url.createObjectUrlFromBlob(blob).toString(),
// )
// ..setAttribute("download", "data.txt")
// ..click();
// }
... ...
import 'dart:async';
// ignore: avoid_web_libraries_in_flutter
import 'dart:html';
import '../../certificates/certificates.dart';
import '../../exceptions/exceptions.dart';
import '../../request/request.dart';
import '../../response/response.dart';
import '../interface/request_base.dart';
import '../utils/body_decoder.dart';
/// A `dart:html` implementation of `HttpRequestBase`.
class HttpRequestImpl implements HttpRequestBase {
HttpRequestImpl({
bool allowAutoSignedCert = true,
List<TrustedCertificate>? trustedCertificates,
this.withCredentials = false,
String Function(Uri url)? findProxy,
});
/// The currently active XHRs.
final _xhrs = <HttpRequest>{};
///This option requires that you submit credentials for requests
///on different sites. The default is false
final bool withCredentials;
@override
Duration? timeout;
/// Sends an HTTP request and asynchronously returns the response.
@override
Future<Response<T>> send<T>(Request<T> request) async {
var bytes = await request.bodyBytes.toBytes();
HttpRequest xhr;
xhr = HttpRequest()
..timeout = timeout?.inMilliseconds
..open(request.method, '${request.url}', async: true); // check this
_xhrs.add(xhr);
xhr
..responseType = 'blob'
..withCredentials = withCredentials;
request.headers.forEach(xhr.setRequestHeader);
var completer = Completer<Response<T>>();
xhr.onLoad.first.then((_) {
var blob = xhr.response as Blob? ?? Blob([]);
var reader = FileReader();
reader.onLoad.first.then((_) async {
var bodyBytes = BodyBytesStream.fromBytes(reader.result as List<int>);
final stringBody =
await bodyBytesToString(bodyBytes, xhr.responseHeaders);
String? contentType;
if (xhr.responseHeaders.containsKey('content-type')) {
contentType = xhr.responseHeaders['content-type'];
} else {
contentType = 'application/json';
}
// xhr.responseHeaders.containsKey(key)
final body = bodyDecoded<T>(
request,
stringBody,
contentType,
);
final response = Response<T>(
bodyBytes: bodyBytes,
statusCode: xhr.status,
request: request,
headers: xhr.responseHeaders,
statusText: xhr.statusText,
body: body,
bodyString: stringBody,
);
completer.complete(response);
});
reader.onError.first.then((error) {
completer.completeError(
GetHttpException(error.toString(), request.url),
StackTrace.current,
);
});
reader.readAsArrayBuffer(blob);
});
xhr.onError.first.then((_) {
completer.completeError(
GetHttpException('XMLHttpRequest error.', request.url),
StackTrace.current);
});
xhr.send(bytes);
try {
return await completer.future;
} finally {
_xhrs.remove(xhr);
}
}
/// Closes the client and abort all active requests.
@override
void close() {
for (var xhr in _xhrs) {
xhr.abort();
}
}
}
... ...
import 'dart:io';
List<int> fileToBytes(dynamic data) {
if (data is File) {
return data.readAsBytesSync();
} else if (data is String) {
if (File(data).existsSync()) {
return File(data).readAsBytesSync();
} else {
throw 'File $data not exists';
}
} else if (data is List<int>) {
return data;
} else {
throw const FormatException(
'File is not "File" or "String" or "List<int>"');
}
}
void writeOnFile(List<int> bytes) {}
... ...
import 'dart:async';
import 'dart:io' as io;
import '../../certificates/certificates.dart';
import '../../exceptions/exceptions.dart';
import '../../request/request.dart';
import '../../response/response.dart';
import '../interface/request_base.dart';
import '../utils/body_decoder.dart';
/// A `dart:io` implementation of `HttpRequestBase`.
class HttpRequestImpl extends HttpRequestBase {
io.HttpClient? _httpClient;
io.SecurityContext? _securityContext;
HttpRequestImpl({
bool allowAutoSignedCert = true,
List<TrustedCertificate>? trustedCertificates,
bool withCredentials = false,
String Function(Uri url)? findProxy,
}) {
_httpClient = io.HttpClient();
if (trustedCertificates != null) {
_securityContext = io.SecurityContext();
for (final trustedCertificate in trustedCertificates) {
_securityContext!
.setTrustedCertificatesBytes(List.from(trustedCertificate.bytes));
}
}
_httpClient = io.HttpClient(context: _securityContext);
_httpClient!.badCertificateCallback = (_, __, ___) => allowAutoSignedCert;
_httpClient!.findProxy = findProxy;
}
@override
Future<Response<T>> send<T>(Request<T> request) async {
var stream = request.bodyBytes.asBroadcastStream();
io.HttpClientRequest? ioRequest;
try {
_httpClient!.connectionTimeout = timeout;
ioRequest = (await _httpClient!.openUrl(request.method, request.url))
..followRedirects = request.followRedirects
..persistentConnection = request.persistentConnection
..maxRedirects = request.maxRedirects
..contentLength = request.contentLength ?? -1;
request.headers.forEach(ioRequest.headers.set);
var response = timeout == null
? await stream.pipe(ioRequest) as io.HttpClientResponse
: await stream.pipe(ioRequest).timeout(timeout!)
as io.HttpClientResponse;
var headers = <String, String>{};
response.headers.forEach((key, values) {
headers[key] = values.join(',');
});
final bodyBytes = (response);
final stringBody = await bodyBytesToString(bodyBytes, headers);
final body = bodyDecoded<T>(
request,
stringBody,
response.headers.contentType?.mimeType,
);
return Response(
headers: headers,
request: request,
statusCode: response.statusCode,
statusText: response.reasonPhrase,
bodyBytes: bodyBytes,
body: body,
bodyString: stringBody,
);
} on TimeoutException catch (_) {
ioRequest?.abort();
rethrow;
} on io.HttpException catch (error) {
throw GetHttpException(error.message, error.uri);
}
}
/// Closes the HttpClient.
@override
void close() {
if (_httpClient != null) {
_httpClient!.close(force: true);
_httpClient = null;
}
}
}
// extension FileExt on io.FileSystemEntity {
// String get fileName {
// return this?.path?.split(io.Platform.pathSeparator)?.last;
// }
// }
... ...
void writeOnFile(List<int> bytes) {}
List<int> fileToBytes(dynamic data) {
throw UnimplementedError();
}
... ...
import '../../certificates/certificates.dart';
import '../../request/request.dart';
import '../../response/response.dart';
import '../interface/request_base.dart';
class HttpRequestImpl extends HttpRequestBase {
HttpRequestImpl({
bool allowAutoSignedCert = true,
List<TrustedCertificate>? trustedCertificates,
bool withCredentials = false,
String Function(Uri url)? findProxy,
});
@override
void close() {}
@override
Future<Response<T>> send<T>(Request<T> request) {
throw UnimplementedError();
}
}
... ...
import '../../request/request.dart';
import '../../response/response.dart';
/// Abstract interface of [HttpRequestImpl].
abstract class HttpRequestBase {
/// Sends an HTTP [Request].
Future<Response<T>> send<T>(Request<T> request);
/// Closes the [Request] and cleans up any resources associated with it.
void close();
/// Gets and sets the timeout.
///
/// For mobile, this value will be applied for both connection and request
/// timeout.
///
/// For web, this value will be the request timeout.
Duration? timeout;
}
... ...