Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
fluttertpc_get
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Jonatas
2020-10-14 15:47:37 -0300
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
0986a355f4082f879cd0ab9685053b5479e65a08
0986a355
1 parent
7b7f21b7
added GetNotifier, improve structure, init refator from scratch
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1042 additions
and
802 deletions
example/lib/pages/home/presentation/views/country_view.dart
example/pubspec.yaml
example/test/main_test.dart
lib/get_instance/src/get_instance.dart
lib/get_instance/src/lifecycle.dart
lib/get_navigation/src/extension_navigation.dart
lib/get_rx/src/rx_core/rx_impl.dart
lib/get_state_manager/get_state_manager.dart
lib/get_state_manager/src/rx_flutter/rx_disposable.dart
lib/get_state_manager/src/rx_flutter/rx_notifier.dart
lib/get_state_manager/src/simple/get_state.dart
lib/get_state_manager/src/simple/get_view.dart
lib/get_state_manager/src/simple/immutable_state.dart
lib/get_state_manager/src/simple/list_notifier.dart
lib/get_state_manager/src/simple/simple_builder.dart
test/instance/get_instance_test.dart
example/lib/pages/home/presentation/views/country_view.dart
View file @
0986a35
...
...
@@ -5,7 +5,7 @@ import 'package:get/get.dart';
import
'../controllers/home_controller.dart'
;
class
CountryView
extends
Get
Widget
<
HomeController
>
{
class
CountryView
extends
Get
View
<
HomeController
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
...
...
example/pubspec.yaml
View file @
0986a35
...
...
@@ -29,7 +29,7 @@ dependencies:
get
:
path
:
../
dio
:
^3.0.9
get_test
:
^3.13.
2
get_test
:
^3.13.
3
dependency_overrides
:
get
:
...
...
example/test/main_test.dart
View file @
0986a35
import
'dart:io'
;
import
'dart:math'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
...
...
@@ -25,6 +26,7 @@ class MockRepository implements IHomeRepository {
}
void
main
(
)
{
setUpAll
(()
=>
HttpOverrides
.
global
=
null
);
final
binding
=
BindingsBuilder
(()
{
Get
.
lazyPut
<
IHomeRepository
>(()
=>
MockRepository
());
Get
.
lazyPut
<
HomeController
>(
...
...
lib/get_instance/src/get_instance.dart
View file @
0986a35
...
...
@@ -11,6 +11,10 @@ class GetInstance {
static
GetInstance
_getInstance
;
T
call
<
T
>()
{
return
find
<
T
>();
}
/// Holds references to every registered Instance when using
/// [Get.put()]
static
final
Map
<
String
,
_InstanceBuilderFactory
>
_singl
=
{};
...
...
@@ -60,6 +64,20 @@ class GetInstance {
_factory
.
putIfAbsent
(
key
,
()
=>
_Lazy
(
builder
,
fenix
));
}
void
injector
<
S
>(
InjectorBuilderCallback
<
S
>
fn
,
{
String
tag
,
bool
fenix
=
false
,
// bool permanent = false,
})
{
lazyPut
(
()
=>
fn
(
this
),
tag:
tag
,
fenix:
fenix
,
// permanent: permanent,
);
}
/// async version of [Get.put()].
/// Awaits for the resolution of the Future from [builder()] parameter and
/// stores the Instance returned.
...
...
@@ -85,7 +103,7 @@ class GetInstance {
S
dependency
,
{
String
tag
,
bool
permanent
=
false
,
InstanceBuilderCallback
<
S
>
builder
,
@deprecated
InstanceBuilderCallback
<
S
>
builder
,
})
{
_insert
(
isSingleton:
true
,
...
...
@@ -201,12 +219,6 @@ class GetInstance {
_routesKey
.
putIfAbsent
(
_getKey
(
S
,
tag
),
()
=>
Get
.
reference
);
}
/// Finds and returns a Instance<[S]> (or [tag]) without further processing.
S
findByType
<
S
>(
Type
type
,
{
String
tag
})
{
final
key
=
_getKey
(
type
,
tag
);
return
_singl
[
key
].
getDependency
()
as
S
;
}
/// Initializes the controller
S
_startController
<
S
>({
String
tag
})
{
final
key
=
_getKey
(
S
,
tag
);
...
...
@@ -216,9 +228,9 @@ class GetInstance {
i
.
onStart
();
Get
.
log
(
'"
$key
" has been initialized'
);
}
if
(!
_singl
[
key
].
isSingleton
&&
i
.
on
Clos
e
!=
null
)
{
if
(!
_singl
[
key
].
isSingleton
&&
i
.
on
Delet
e
!=
null
)
{
_routesByCreate
[
Get
.
reference
]
??=
HashSet
<
Function
>();
_routesByCreate
[
Get
.
reference
].
add
(
i
.
on
Clos
e
);
_routesByCreate
[
Get
.
reference
].
add
(
i
.
on
Delet
e
);
}
}
return
i
;
...
...
@@ -349,7 +361,7 @@ class GetInstance {
return
false
;
}
if
(
i
is
GetLifeCycle
)
{
i
.
on
Clos
e
();
i
.
on
Delet
e
();
Get
.
log
(
'"
$newKey
" onClose() called'
);
}
...
...
@@ -375,6 +387,8 @@ class GetInstance {
typedef
InstanceBuilderCallback
<
S
>
=
S
Function
();
typedef
InjectorBuilderCallback
<
S
>
=
S
Function
(
GetInstance
);
typedef
AsyncInstanceBuilderCallback
<
S
>
=
Future
<
S
>
Function
();
/// Internal class to register instances with Get.[put]<[S]>().
...
...
@@ -413,6 +427,7 @@ class _InstanceBuilderFactory<S> {
/// keeps a reference to the callback to be called.
class
_Lazy
{
bool
fenix
;
bool
permanent
=
false
;
InstanceBuilderCallback
builder
;
_Lazy
(
this
.
builder
,
this
.
fenix
);
...
...
lib/get_instance/src/lifecycle.dart
View file @
0986a35
...
...
@@ -11,13 +11,15 @@ class _InternalFinalCallback<T> {
T
call
()
=>
callback
.
call
();
}
abstract
class
GetLifeCycle
{
mixin
GetLifeCycle
{
/// Called at the exact moment the widget is allocated in memory.
/// It uses an internal "callable" type, to avoid any @overrides in subclases.
/// This method should be internal and is required to define the
/// lifetime cycle of the subclass.
final
onStart
=
_InternalFinalCallback
<
void
>();
final
onDelete
=
_InternalFinalCallback
<
void
>();
/// Called immediately after the widget is allocated in memory.
/// You might use this to initialize something for the controller.
void
onInit
()
{}
...
...
lib/get_navigation/src/extension_navigation.dart
View file @
0986a35
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'../../get_core/get_core.dart'
;
...
...
@@ -11,510 +13,279 @@ import 'routes/transitions_type.dart';
//TODO: Split this class on "Snackbar" "Dialog" "bottomSheet"
//and "navigation" extensions
extension
GetNavigation
on
GetInterface
{
/// **Navigation.push()** shortcut.<br><br>
///
/// Pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future
<
T
>
to
<
T
>(
Widget
page
,
{
bool
opaque
,
Transition
transition
,
Curve
curve
,
Duration
duration
,
int
id
,
bool
fullscreenDialog
=
false
,
dynamic
arguments
,
Bindings
binding
,
bool
preventDuplicates
=
true
,
bool
popGesture
,
})
{
var
routeName
=
"/
${page.runtimeType.toString()}
"
;
if
(
preventDuplicates
&&
routeName
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)?.
currentState
?.
push
(
GetPageRoute
(
opaque:
opaque
??
true
,
page:
()
=>
page
,
routeName:
routeName
,
settings:
RouteSettings
(
// name: forceRouteName ? '${a.runtimeType}' : '',
arguments:
arguments
,
),
popGesture:
popGesture
??
defaultPopGesture
,
transition:
transition
??
defaultTransition
,
curve:
curve
??
defaultTransitionCurve
,
fullscreenDialog:
fullscreenDialog
,
binding:
binding
,
transitionDuration:
duration
??
defaultTransitionDuration
,
),
);
}
/// **Navigation.pushNamed()** shortcut.<br><br>
///
/// Pushes a new named [page] to the stack.
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future
<
T
>
toNamed
<
T
>(
String
page
,
{
dynamic
arguments
,
int
id
,
bool
preventDuplicates
=
true
,
})
{
if
(
preventDuplicates
&&
page
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)?.
currentState
?.
pushNamed
(
page
,
arguments:
arguments
);
}
extension
ExtensionSnackbar
on
GetInterface
{
void
rawSnackbar
({
String
title
,
String
message
,
Widget
titleText
,
Widget
messageText
,
Widget
icon
,
bool
instantInit
=
true
,
bool
shouldIconPulse
=
true
,
double
maxWidth
,
EdgeInsets
margin
=
const
EdgeInsets
.
all
(
0.0
),
EdgeInsets
padding
=
const
EdgeInsets
.
all
(
16
),
double
borderRadius
=
0.0
,
Color
borderColor
,
double
borderWidth
=
1.0
,
Color
backgroundColor
=
const
Color
(
0xFF303030
),
Color
leftBarIndicatorColor
,
List
<
BoxShadow
>
boxShadows
,
Gradient
backgroundGradient
,
FlatButton
mainButton
,
OnTap
onTap
,
Duration
duration
=
const
Duration
(
seconds:
3
),
bool
isDismissible
=
true
,
SnackDismissDirection
dismissDirection
=
SnackDismissDirection
.
VERTICAL
,
bool
showProgressIndicator
=
false
,
AnimationController
progressIndicatorController
,
Color
progressIndicatorBackgroundColor
,
Animation
<
Color
>
progressIndicatorValueColor
,
SnackPosition
snackPosition
=
SnackPosition
.
BOTTOM
,
SnackStyle
snackStyle
=
SnackStyle
.
FLOATING
,
Curve
forwardAnimationCurve
=
Curves
.
easeOutCirc
,
Curve
reverseAnimationCurve
=
Curves
.
easeOutCirc
,
Duration
animationDuration
=
const
Duration
(
seconds:
1
),
SnackbarStatusCallback
snackbarStatus
,
double
barBlur
=
0.0
,
double
overlayBlur
=
0.0
,
Color
overlayColor
,
Form
userInputForm
,
})
async
{
final
getBar
=
GetBar
(
snackbarStatus:
snackbarStatus
,
title:
title
,
message:
message
,
titleText:
titleText
,
messageText:
messageText
,
snackPosition:
snackPosition
,
borderRadius:
borderRadius
,
margin:
margin
,
duration:
duration
,
barBlur:
barBlur
,
backgroundColor:
backgroundColor
,
icon:
icon
,
shouldIconPulse:
shouldIconPulse
,
maxWidth:
maxWidth
,
padding:
padding
,
borderColor:
borderColor
,
borderWidth:
borderWidth
,
leftBarIndicatorColor:
leftBarIndicatorColor
,
boxShadows:
boxShadows
,
backgroundGradient:
backgroundGradient
,
mainButton:
mainButton
,
onTap:
onTap
,
isDismissible:
isDismissible
,
dismissDirection:
dismissDirection
,
showProgressIndicator:
showProgressIndicator
??
false
,
progressIndicatorController:
progressIndicatorController
,
progressIndicatorBackgroundColor:
progressIndicatorBackgroundColor
,
progressIndicatorValueColor:
progressIndicatorValueColor
,
snackStyle:
snackStyle
,
forwardAnimationCurve:
forwardAnimationCurve
,
reverseAnimationCurve:
reverseAnimationCurve
,
animationDuration:
animationDuration
,
overlayBlur:
overlayBlur
,
overlayColor:
overlayColor
,
userInputForm:
userInputForm
,
);
/// **Navigation.pushReplacementNamed()** shortcut.<br><br>
///
/// Pop the current named [page] in the stack and push a new one in its place
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future
<
T
>
offNamed
<
T
>(
String
page
,
{
dynamic
arguments
,
int
id
,
bool
preventDuplicates
=
true
,
})
{
if
(
preventDuplicates
&&
page
==
currentRoute
)
{
return
null
;
if
(
instantInit
)
{
getBar
.
show
();
}
else
{
SchedulerBinding
.
instance
.
addPostFrameCallback
((
_
)
{
getBar
.
show
();
});
}
return
global
(
id
)
?.
currentState
?.
pushReplacementNamed
(
page
,
arguments:
arguments
);
}
/// **Navigation.popUntil()** shortcut.<br><br>
///
/// Calls pop several times in the stack until [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the
/// dialog is closed
void
until
(
RoutePredicate
predicate
,
{
int
id
})
{
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return
global
(
id
)?.
currentState
?.
popUntil
(
predicate
);
Future
<
T
>
showSnackbar
<
T
>(
GetBar
snackbar
)
{
return
key
?.
currentState
?.
push
(
SnackRoute
<
T
>(
snack:
snackbar
));
}
/// **Navigation.pushAndRemoveUntil()** shortcut.<br><br>
///
/// Push the given [page], and then pop several pages in the stack until
/// [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Obs: unlike other get methods, this one you need to send a function
/// that returns the widget to the page argument, like this:
/// Get.offUntil( () => HomePage() )
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
Future
<
T
>
offUntil
<
T
>(
Route
<
T
>
page
,
RoutePredicate
predicate
,
{
int
id
})
{
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return
global
(
id
)?.
currentState
?.
pushAndRemoveUntil
(
page
,
predicate
);
}
void
snackbar
(
String
title
,
String
message
,
{
Color
colorText
,
Duration
duration
,
/// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
///
/// Push the given named [page], and then pop several pages in the stack
/// until [predicate] returns true
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future
<
T
>
offNamedUntil
<
T
>(
String
page
,
RoutePredicate
predicate
,
{
int
id
,
dynamic
arguments
,
})
{
return
global
(
id
)
?.
currentState
?.
pushNamedAndRemoveUntil
(
page
,
predicate
,
arguments:
arguments
);
/// with instantInit = false you can put snackbar on initState
bool
instantInit
=
true
,
SnackPosition
snackPosition
,
Widget
titleText
,
Widget
messageText
,
Widget
icon
,
bool
shouldIconPulse
,
double
maxWidth
,
EdgeInsets
margin
,
EdgeInsets
padding
,
double
borderRadius
,
Color
borderColor
,
double
borderWidth
,
Color
backgroundColor
,
Color
leftBarIndicatorColor
,
List
<
BoxShadow
>
boxShadows
,
Gradient
backgroundGradient
,
FlatButton
mainButton
,
OnTap
onTap
,
bool
isDismissible
,
bool
showProgressIndicator
,
SnackDismissDirection
dismissDirection
,
AnimationController
progressIndicatorController
,
Color
progressIndicatorBackgroundColor
,
Animation
<
Color
>
progressIndicatorValueColor
,
SnackStyle
snackStyle
,
Curve
forwardAnimationCurve
,
Curve
reverseAnimationCurve
,
Duration
animationDuration
,
double
barBlur
,
double
overlayBlur
,
SnackbarStatusCallback
snackbarStatus
,
Color
overlayColor
,
Form
userInputForm
,
})
async
{
final
getBar
=
GetBar
(
snackbarStatus:
snackbarStatus
,
titleText:
(
title
==
null
)
?
null
:
titleText
??
Text
(
title
,
style:
TextStyle
(
color:
colorText
??
iconColor
??
Colors
.
black
,
fontWeight:
FontWeight
.
w800
,
fontSize:
16
,
),
),
messageText:
messageText
??
Text
(
message
,
style:
TextStyle
(
color:
colorText
??
iconColor
??
Colors
.
black
,
fontWeight:
FontWeight
.
w300
,
fontSize:
14
,
),
),
snackPosition:
snackPosition
??
SnackPosition
.
TOP
,
borderRadius:
borderRadius
??
15
,
margin:
margin
??
EdgeInsets
.
symmetric
(
horizontal:
10
),
duration:
duration
??
Duration
(
seconds:
3
),
barBlur:
barBlur
??
7.0
,
backgroundColor:
backgroundColor
??
Colors
.
grey
.
withOpacity
(
0.2
),
icon:
icon
,
shouldIconPulse:
shouldIconPulse
??
true
,
maxWidth:
maxWidth
,
padding:
padding
??
EdgeInsets
.
all
(
16
),
borderColor:
borderColor
,
borderWidth:
borderWidth
,
leftBarIndicatorColor:
leftBarIndicatorColor
,
boxShadows:
boxShadows
,
backgroundGradient:
backgroundGradient
,
mainButton:
mainButton
,
onTap:
onTap
,
isDismissible:
isDismissible
??
true
,
dismissDirection:
dismissDirection
??
SnackDismissDirection
.
VERTICAL
,
showProgressIndicator:
showProgressIndicator
??
false
,
progressIndicatorController:
progressIndicatorController
,
progressIndicatorBackgroundColor:
progressIndicatorBackgroundColor
,
progressIndicatorValueColor:
progressIndicatorValueColor
,
snackStyle:
snackStyle
??
SnackStyle
.
FLOATING
,
forwardAnimationCurve:
forwardAnimationCurve
??
Curves
.
easeOutCirc
,
reverseAnimationCurve:
reverseAnimationCurve
??
Curves
.
easeOutCirc
,
animationDuration:
animationDuration
??
Duration
(
seconds:
1
),
overlayBlur:
overlayBlur
??
0.0
,
overlayColor:
overlayColor
??
Colors
.
transparent
,
userInputForm:
userInputForm
);
if
(
instantInit
)
{
showSnackbar
(
getBar
);
}
else
{
routing
.
isSnackbar
=
true
;
SchedulerBinding
.
instance
.
addPostFrameCallback
((
_
)
{
showSnackbar
(
getBar
);
});
}
}
}
/// **Navigation.popAndPushNamed()** shortcut.<br><br>
///
/// Pop the current named page and pushes a new [page] to the stack
/// in its place
///
/// You can send any type of value to the other route in the [arguments].
/// It is very similar to `offNamed()` but use a different approach
///
/// The `offNamed()` pop a page, and goes to the next. The
/// `offAndToNamed()` goes to the next page, and removes the previous one.
/// The route transition animation is different.
Future
<
T
>
offAndToNamed
<
T
>(
String
page
,
{
dynamic
arguments
,
int
id
,
dynamic
result
,
extension
ExtensionDialog
on
GetInterface
{
/// Show a dialog.
/// You can pass a [transitionDuration] and/or [transitionCurve],
/// overriding the defaults when the dialog shows up and closes.
/// When the dialog closes, uses those animations in reverse.
Future
<
T
>
dialog
<
T
>(
Widget
widget
,
{
bool
barrierDismissible
=
true
,
Color
barrierColor
,
bool
useSafeArea
=
true
,
bool
useRootNavigator
=
true
,
RouteSettings
routeSettings
,
Duration
transitionDuration
,
Curve
transitionCurve
,
})
{
return
global
(
id
)
?.
currentState
?.
popAndPushNamed
(
page
,
arguments:
arguments
,
result:
result
);
}
assert
(
widget
!=
null
);
assert
(
barrierDismissible
!=
null
);
assert
(
useSafeArea
!=
null
);
assert
(
useRootNavigator
!=
null
);
assert
(
debugCheckHasMaterialLocalizations
(
context
));
/// **Navigation.removeRoute()** shortcut.<br><br>
///
/// Remove a specific [route] from the stack
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void
removeRoute
(
Route
<
dynamic
>
route
,
{
int
id
})
{
return
global
(
id
)?.
currentState
?.
removeRoute
(
route
);
final
theme
=
Theme
.
of
(
context
,
shadowThemeOnly:
true
);
return
generalDialog
(
pageBuilder:
(
buildContext
,
animation
,
secondaryAnimation
)
{
final
pageChild
=
widget
;
Widget
dialog
=
Builder
(
builder:
(
context
)
{
return
theme
!=
null
?
Theme
(
data:
theme
,
child:
pageChild
)
:
pageChild
;
});
if
(
useSafeArea
)
{
dialog
=
SafeArea
(
child:
dialog
);
}
return
dialog
;
},
barrierDismissible:
barrierDismissible
,
barrierLabel:
MaterialLocalizations
.
of
(
context
).
modalBarrierDismissLabel
,
barrierColor:
barrierColor
??
Colors
.
black54
,
transitionDuration:
transitionDuration
??
defaultDialogTransitionDuration
,
transitionBuilder:
(
context
,
animation
,
secondaryAnimation
,
child
)
{
return
FadeTransition
(
opacity:
CurvedAnimation
(
parent:
animation
,
curve:
transitionCurve
??
defaultDialogTransitionCurve
,
),
child:
child
,
);
},
useRootNavigator:
useRootNavigator
,
routeSettings:
routeSettings
,
);
}
/// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
///
/// Push a named [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context, so you can
/// call from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
Future
<
T
>
offAllNamed
<
T
>(
String
newRouteName
,
{
RoutePredicate
predicate
,
dynamic
arguments
,
int
id
,
/// Api from showGeneralDialog with no context
Future
<
T
>
generalDialog
<
T
>({
@required
RoutePageBuilder
pageBuilder
,
bool
barrierDismissible
=
false
,
String
barrierLabel
,
Color
barrierColor
=
const
Color
(
0x80000000
),
Duration
transitionDuration
=
const
Duration
(
milliseconds:
200
),
RouteTransitionsBuilder
transitionBuilder
,
bool
useRootNavigator
=
true
,
RouteSettings
routeSettings
,
})
{
return
global
(
id
)?.
currentState
?.
pushNamedAndRemoveUntil
(
newRouteName
,
predicate
??
(
_
)
=>
false
,
arguments:
arguments
,
);
}
/// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN
bool
get
isOverlaysOpen
=>
(
isSnackbarOpen
||
isDialogOpen
||
isBottomSheetOpen
);
/// Returns true if there is no Snackbar, Dialog or BottomSheet open
bool
get
isOverlaysClosed
=>
(!
isSnackbarOpen
&&
!
isDialogOpen
&&
!
isBottomSheetOpen
);
/// **Navigation.popUntil()** shortcut.<br><br>
///
/// Pop the current page, snackbar, dialog or bottomsheet in the stack
///
/// if your set [closeOverlays] to true, Get.back() will close the
/// currently open snackbar/dialog/bottomsheet AND the current page
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
void
back
({
dynamic
result
,
bool
closeOverlays
=
false
,
bool
canPop
=
true
,
int
id
,
})
{
if
(
closeOverlays
&&
isOverlaysOpen
)
{
navigator
?.
popUntil
((
route
)
{
return
(
isOverlaysClosed
);
});
}
if
(
canPop
)
{
if
(
global
(
id
)?.
currentState
?.
canPop
()
==
true
)
{
global
(
id
)?.
currentState
?.
pop
(
result
);
}
}
else
{
global
(
id
)?.
currentState
?.
pop
(
result
);
}
}
/// **Navigation.popUntil()** (with predicate) shortcut .<br><br>
///
/// Close as many routes as defined by [times]
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void
close
(
int
times
,
[
int
id
])
{
if
((
times
==
null
)
||
(
times
<
1
))
{
times
=
1
;
}
var
count
=
0
;
var
back
=
global
(
id
)?.
currentState
?.
popUntil
((
route
)
=>
count
++
==
times
);
return
back
;
}
/// **Navigation.pushReplacement()** shortcut .<br><br>
///
/// Pop the current page and pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], define a Tween [curve],
/// and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future
<
T
>
off
<
T
>(
Widget
page
,
{
bool
opaque
=
false
,
Transition
transition
,
Curve
curve
,
bool
popGesture
,
int
id
,
dynamic
arguments
,
Bindings
binding
,
bool
fullscreenDialog
=
false
,
bool
preventDuplicates
=
true
,
Duration
duration
,
})
{
var
routeName
=
"/
${page.runtimeType.toString()}
"
;
if
(
preventDuplicates
&&
routeName
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)?.
currentState
?.
pushReplacement
(
GetPageRoute
(
opaque:
opaque
??
true
,
page:
()
=>
page
,
binding:
binding
,
settings:
RouteSettings
(
arguments:
arguments
),
routeName:
routeName
,
fullscreenDialog:
fullscreenDialog
,
popGesture:
popGesture
??
defaultPopGesture
,
transition:
transition
??
defaultTransition
,
curve:
curve
??
defaultTransitionCurve
,
transitionDuration:
duration
??
defaultTransitionDuration
));
}
/// **Navigation.pushAndRemoveUntil()** shortcut .<br><br>
///
/// Push a [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], a [curve] and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future
<
T
>
offAll
<
T
>(
Widget
page
,
{
RoutePredicate
predicate
,
bool
opaque
=
false
,
bool
popGesture
,
int
id
,
dynamic
arguments
,
Bindings
binding
,
bool
fullscreenDialog
=
false
,
Transition
transition
,
Curve
curve
,
Duration
duration
,
})
{
var
routeName
=
"/
${page.runtimeType.toString()}
"
;
return
global
(
id
)?.
currentState
?.
pushAndRemoveUntil
(
GetPageRoute
(
opaque:
opaque
??
true
,
popGesture:
popGesture
??
defaultPopGesture
,
page:
()
=>
page
,
binding:
binding
,
settings:
RouteSettings
(
arguments:
arguments
),
fullscreenDialog:
fullscreenDialog
,
routeName:
routeName
,
transition:
transition
??
defaultTransition
,
curve:
curve
??
defaultTransitionCurve
,
transitionDuration:
duration
??
defaultTransitionDuration
,
),
predicate
??
(
route
)
=>
false
);
}
/// Show a dialog.
/// You can pass a [transitionDuration] and/or [transitionCurve],
/// overriding the defaults when the dialog shows up and closes.
/// When the dialog closes, uses those animations in reverse.
Future
<
T
>
dialog
<
T
>(
Widget
widget
,
{
bool
barrierDismissible
=
true
,
Color
barrierColor
,
bool
useSafeArea
=
true
,
bool
useRootNavigator
=
true
,
RouteSettings
routeSettings
,
Duration
transitionDuration
,
Curve
transitionCurve
,
})
{
assert
(
widget
!=
null
);
assert
(
barrierDismissible
!=
null
);
assert
(
useSafeArea
!=
null
);
assert
(
useRootNavigator
!=
null
);
assert
(
debugCheckHasMaterialLocalizations
(
context
));
final
theme
=
Theme
.
of
(
context
,
shadowThemeOnly:
true
);
return
generalDialog
(
pageBuilder:
(
buildContext
,
animation
,
secondaryAnimation
)
{
final
pageChild
=
widget
;
Widget
dialog
=
Builder
(
builder:
(
context
)
{
return
theme
!=
null
?
Theme
(
data:
theme
,
child:
pageChild
)
:
pageChild
;
});
if
(
useSafeArea
)
{
dialog
=
SafeArea
(
child:
dialog
);
}
return
dialog
;
},
barrierDismissible:
barrierDismissible
,
barrierLabel:
MaterialLocalizations
.
of
(
context
).
modalBarrierDismissLabel
,
barrierColor:
barrierColor
??
Colors
.
black54
,
transitionDuration:
transitionDuration
??
defaultDialogTransitionDuration
,
transitionBuilder:
(
context
,
animation
,
secondaryAnimation
,
child
)
{
return
FadeTransition
(
opacity:
CurvedAnimation
(
parent:
animation
,
curve:
transitionCurve
??
defaultDialogTransitionCurve
,
),
child:
child
,
);
},
useRootNavigator:
useRootNavigator
,
routeSettings:
routeSettings
,
);
}
/// Api from showGeneralDialog with no context
Future
<
T
>
generalDialog
<
T
>({
@required
RoutePageBuilder
pageBuilder
,
bool
barrierDismissible
=
false
,
String
barrierLabel
,
Color
barrierColor
=
const
Color
(
0x80000000
),
Duration
transitionDuration
=
const
Duration
(
milliseconds:
200
),
RouteTransitionsBuilder
transitionBuilder
,
bool
useRootNavigator
=
true
,
RouteSettings
routeSettings
,
})
{
assert
(
pageBuilder
!=
null
);
assert
(
useRootNavigator
!=
null
);
assert
(!
barrierDismissible
||
barrierLabel
!=
null
);
return
Navigator
.
of
(
overlayContext
,
rootNavigator:
useRootNavigator
)
.
push
<
T
>(
GetDialogRoute
<
T
>(
pageBuilder:
pageBuilder
,
barrierDismissible:
barrierDismissible
,
barrierLabel:
barrierLabel
,
barrierColor:
barrierColor
,
transitionDuration:
transitionDuration
,
transitionBuilder:
transitionBuilder
,
settings:
routeSettings
,
));
assert
(
pageBuilder
!=
null
);
assert
(
useRootNavigator
!=
null
);
assert
(!
barrierDismissible
||
barrierLabel
!=
null
);
return
Navigator
.
of
(
overlayContext
,
rootNavigator:
useRootNavigator
)
.
push
<
T
>(
GetDialogRoute
<
T
>(
pageBuilder:
pageBuilder
,
barrierDismissible:
barrierDismissible
,
barrierLabel:
barrierLabel
,
barrierColor:
barrierColor
,
transitionDuration:
transitionDuration
,
transitionBuilder:
transitionBuilder
,
settings:
routeSettings
,
));
}
/// Custom UI Dialog.
...
...
@@ -623,7 +394,9 @@ extension GetNavigation on GetInterface {
barrierDismissible:
barrierDismissible
,
);
}
}
extension
ExtensionBottomSheet
on
GetInterface
{
Future
<
T
>
bottomSheet
<
T
>(
Widget
bottomsheet
,
{
Color
backgroundColor
,
...
...
@@ -667,198 +440,434 @@ extension GetNavigation on GetInterface {
enableDrag:
enableDrag
,
));
}
}
void
rawSnackbar
({
String
title
,
String
message
,
Widget
titleText
,
Widget
messageText
,
Widget
icon
,
bool
instantInit
=
true
,
bool
shouldIconPulse
=
true
,
double
maxWidth
,
EdgeInsets
margin
=
const
EdgeInsets
.
all
(
0.0
),
EdgeInsets
padding
=
const
EdgeInsets
.
all
(
16
),
double
borderRadius
=
0.0
,
Color
borderColor
,
double
borderWidth
=
1.0
,
Color
backgroundColor
=
const
Color
(
0xFF303030
),
Color
leftBarIndicatorColor
,
List
<
BoxShadow
>
boxShadows
,
Gradient
backgroundGradient
,
FlatButton
mainButton
,
OnTap
onTap
,
Duration
duration
=
const
Duration
(
seconds:
3
),
bool
isDismissible
=
true
,
SnackDismissDirection
dismissDirection
=
SnackDismissDirection
.
VERTICAL
,
bool
showProgressIndicator
=
false
,
AnimationController
progressIndicatorController
,
Color
progressIndicatorBackgroundColor
,
Animation
<
Color
>
progressIndicatorValueColor
,
SnackPosition
snackPosition
=
SnackPosition
.
BOTTOM
,
SnackStyle
snackStyle
=
SnackStyle
.
FLOATING
,
Curve
forwardAnimationCurve
=
Curves
.
easeOutCirc
,
Curve
reverseAnimationCurve
=
Curves
.
easeOutCirc
,
Duration
animationDuration
=
const
Duration
(
seconds:
1
),
SnackbarStatusCallback
snackbarStatus
,
double
barBlur
=
0.0
,
double
overlayBlur
=
0.0
,
Color
overlayColor
,
Form
userInputForm
,
})
async
{
final
getBar
=
GetBar
(
snackbarStatus:
snackbarStatus
,
title:
title
,
message:
message
,
titleText:
titleText
,
messageText:
messageText
,
snackPosition:
snackPosition
,
borderRadius:
borderRadius
,
margin:
margin
,
duration:
duration
,
barBlur:
barBlur
,
backgroundColor:
backgroundColor
,
icon:
icon
,
shouldIconPulse:
shouldIconPulse
,
maxWidth:
maxWidth
,
padding:
padding
,
borderColor:
borderColor
,
borderWidth:
borderWidth
,
leftBarIndicatorColor:
leftBarIndicatorColor
,
boxShadows:
boxShadows
,
backgroundGradient:
backgroundGradient
,
mainButton:
mainButton
,
onTap:
onTap
,
isDismissible:
isDismissible
,
dismissDirection:
dismissDirection
,
showProgressIndicator:
showProgressIndicator
??
false
,
progressIndicatorController:
progressIndicatorController
,
progressIndicatorBackgroundColor:
progressIndicatorBackgroundColor
,
progressIndicatorValueColor:
progressIndicatorValueColor
,
snackStyle:
snackStyle
,
forwardAnimationCurve:
forwardAnimationCurve
,
reverseAnimationCurve:
reverseAnimationCurve
,
animationDuration:
animationDuration
,
overlayBlur:
overlayBlur
,
overlayColor:
overlayColor
,
userInputForm:
userInputForm
,
);
extension
GetNavigation
on
GetInterface
{
/// **Navigation.push()** shortcut.<br><br>
///
/// Pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future
<
T
>
to
<
T
>(
Widget
page
,
{
bool
opaque
,
Transition
transition
,
Curve
curve
,
Duration
duration
,
int
id
,
bool
fullscreenDialog
=
false
,
dynamic
arguments
,
Bindings
binding
,
bool
preventDuplicates
=
true
,
bool
popGesture
,
})
{
var
routeName
=
"/
${page.runtimeType.toString()}
"
;
if
(
preventDuplicates
&&
routeName
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)?.
currentState
?.
push
(
GetPageRoute
(
opaque:
opaque
??
true
,
page:
()
=>
page
,
routeName:
routeName
,
settings:
RouteSettings
(
// name: forceRouteName ? '${a.runtimeType}' : '',
arguments:
arguments
,
),
popGesture:
popGesture
??
defaultPopGesture
,
transition:
transition
??
defaultTransition
,
curve:
curve
??
defaultTransitionCurve
,
fullscreenDialog:
fullscreenDialog
,
binding:
binding
,
transitionDuration:
duration
??
defaultTransitionDuration
,
),
);
}
if
(
instantInit
)
{
getBar
.
show
();
}
else
{
SchedulerBinding
.
instance
.
addPostFrameCallback
((
_
)
{
getBar
.
show
();
/// **Navigation.pushNamed()** shortcut.<br><br>
///
/// Pushes a new named [page] to the stack.
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future
<
T
>
toNamed
<
T
>(
String
page
,
{
dynamic
arguments
,
int
id
,
bool
preventDuplicates
=
true
,
})
{
if
(
preventDuplicates
&&
page
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)?.
currentState
?.
pushNamed
(
page
,
arguments:
arguments
);
}
/// **Navigation.pushReplacementNamed()** shortcut.<br><br>
///
/// Pop the current named [page] in the stack and push a new one in its place
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future
<
T
>
offNamed
<
T
>(
String
page
,
{
dynamic
arguments
,
int
id
,
bool
preventDuplicates
=
true
,
})
{
if
(
preventDuplicates
&&
page
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)
?.
currentState
?.
pushReplacementNamed
(
page
,
arguments:
arguments
);
}
/// **Navigation.popUntil()** shortcut.<br><br>
///
/// Calls pop several times in the stack until [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the
/// dialog is closed
void
until
(
RoutePredicate
predicate
,
{
int
id
})
{
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return
global
(
id
)?.
currentState
?.
popUntil
(
predicate
);
}
/// **Navigation.pushAndRemoveUntil()** shortcut.<br><br>
///
/// Push the given [page], and then pop several pages in the stack until
/// [predicate] returns true
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Obs: unlike other get methods, this one you need to send a function
/// that returns the widget to the page argument, like this:
/// Get.offUntil( () => HomePage() )
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
///
/// or also like this:
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
Future
<
T
>
offUntil
<
T
>(
Route
<
T
>
page
,
RoutePredicate
predicate
,
{
int
id
})
{
// if (key.currentState.mounted) // add this if appear problems on future with route navigate
// when widget don't mounted
return
global
(
id
)?.
currentState
?.
pushAndRemoveUntil
(
page
,
predicate
);
}
/// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
///
/// Push the given named [page], and then pop several pages in the stack
/// until [predicate] returns true
///
/// You can send any type of value to the other route in the [arguments].
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// Note: Always put a slash on the route ('/page1'), to avoid unnexpected errors
Future
<
T
>
offNamedUntil
<
T
>(
String
page
,
RoutePredicate
predicate
,
{
int
id
,
dynamic
arguments
,
})
{
return
global
(
id
)
?.
currentState
?.
pushNamedAndRemoveUntil
(
page
,
predicate
,
arguments:
arguments
);
}
/// **Navigation.popAndPushNamed()** shortcut.<br><br>
///
/// Pop the current named page and pushes a new [page] to the stack
/// in its place
///
/// You can send any type of value to the other route in the [arguments].
/// It is very similar to `offNamed()` but use a different approach
///
/// The `offNamed()` pop a page, and goes to the next. The
/// `offAndToNamed()` goes to the next page, and removes the previous one.
/// The route transition animation is different.
Future
<
T
>
offAndToNamed
<
T
>(
String
page
,
{
dynamic
arguments
,
int
id
,
dynamic
result
,
})
{
return
global
(
id
)
?.
currentState
?.
popAndPushNamed
(
page
,
arguments:
arguments
,
result:
result
);
}
/// **Navigation.removeRoute()** shortcut.<br><br>
///
/// Remove a specific [route] from the stack
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void
removeRoute
(
Route
<
dynamic
>
route
,
{
int
id
})
{
return
global
(
id
)?.
currentState
?.
removeRoute
(
route
);
}
/// **Navigation.pushNamedAndRemoveUntil()** shortcut.<br><br>
///
/// Push a named [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context, so you can
/// call from your business logic.
///
/// You can send any type of value to the other route in the [arguments].
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// Note: Always put a slash on the route ('/page1'), to avoid unexpected errors
Future
<
T
>
offAllNamed
<
T
>(
String
newRouteName
,
{
RoutePredicate
predicate
,
dynamic
arguments
,
int
id
,
})
{
return
global
(
id
)?.
currentState
?.
pushNamedAndRemoveUntil
(
newRouteName
,
predicate
??
(
_
)
=>
false
,
arguments:
arguments
,
);
}
/// Returns true if a Snackbar, Dialog or BottomSheet is currently OPEN
bool
get
isOverlaysOpen
=>
(
isSnackbarOpen
||
isDialogOpen
||
isBottomSheetOpen
);
/// Returns true if there is no Snackbar, Dialog or BottomSheet open
bool
get
isOverlaysClosed
=>
(!
isSnackbarOpen
&&
!
isDialogOpen
&&
!
isBottomSheetOpen
);
/// **Navigation.popUntil()** shortcut.<br><br>
///
/// Pop the current page, snackbar, dialog or bottomsheet in the stack
///
/// if your set [closeOverlays] to true, Get.back() will close the
/// currently open snackbar/dialog/bottomsheet AND the current page
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// It has the advantage of not needing context, so you can call
/// from your business logic.
void
back
({
dynamic
result
,
bool
closeOverlays
=
false
,
bool
canPop
=
true
,
int
id
,
})
{
if
(
closeOverlays
&&
isOverlaysOpen
)
{
navigator
?.
popUntil
((
route
)
{
return
(
isOverlaysClosed
);
});
}
if
(
canPop
)
{
if
(
global
(
id
)?.
currentState
?.
canPop
()
==
true
)
{
global
(
id
)?.
currentState
?.
pop
(
result
);
}
}
else
{
global
(
id
)?.
currentState
?.
pop
(
result
);
}
}
Future
<
T
>
showSnackbar
<
T
>(
GetBar
snackbar
)
{
return
key
?.
currentState
?.
push
(
SnackRoute
<
T
>(
snack:
snackbar
));
/// **Navigation.popUntil()** (with predicate) shortcut .<br><br>
///
/// Close as many routes as defined by [times]
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
void
close
(
int
times
,
[
int
id
])
{
if
((
times
==
null
)
||
(
times
<
1
))
{
times
=
1
;
}
var
count
=
0
;
var
back
=
global
(
id
)?.
currentState
?.
popUntil
((
route
)
=>
count
++
==
times
);
return
back
;
}
void
snackbar
(
String
title
,
String
message
,
{
Color
colorText
,
/// **Navigation.pushReplacement()** shortcut .<br><br>
///
/// Pop the current page and pushes a new [page] to the stack
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], define a Tween [curve],
/// and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future
<
T
>
off
<
T
>(
Widget
page
,
{
bool
opaque
=
false
,
Transition
transition
,
Curve
curve
,
bool
popGesture
,
int
id
,
dynamic
arguments
,
Bindings
binding
,
bool
fullscreenDialog
=
false
,
bool
preventDuplicates
=
true
,
Duration
duration
,
})
{
var
routeName
=
"/
${page.runtimeType.toString()}
"
;
if
(
preventDuplicates
&&
routeName
==
currentRoute
)
{
return
null
;
}
return
global
(
id
)?.
currentState
?.
pushReplacement
(
GetPageRoute
(
opaque:
opaque
??
true
,
page:
()
=>
page
,
binding:
binding
,
settings:
RouteSettings
(
arguments:
arguments
),
routeName:
routeName
,
fullscreenDialog:
fullscreenDialog
,
popGesture:
popGesture
??
defaultPopGesture
,
transition:
transition
??
defaultTransition
,
curve:
curve
??
defaultTransitionCurve
,
transitionDuration:
duration
??
defaultTransitionDuration
));
}
/// with instantInit = false you can put snackbar on initState
bool
instantInit
=
true
,
SnackPosition
snackPosition
,
Widget
titleText
,
Widget
messageText
,
Widget
icon
,
bool
shouldIconPulse
,
double
maxWidth
,
EdgeInsets
margin
,
EdgeInsets
padding
,
double
borderRadius
,
Color
borderColor
,
double
borderWidth
,
Color
backgroundColor
,
Color
leftBarIndicatorColor
,
List
<
BoxShadow
>
boxShadows
,
Gradient
backgroundGradient
,
FlatButton
mainButton
,
OnTap
onTap
,
bool
isDismissible
,
bool
showProgressIndicator
,
SnackDismissDirection
dismissDirection
,
AnimationController
progressIndicatorController
,
Color
progressIndicatorBackgroundColor
,
Animation
<
Color
>
progressIndicatorValueColor
,
SnackStyle
snackStyle
,
Curve
forwardAnimationCurve
,
Curve
reverseAnimationCurve
,
Duration
animationDuration
,
double
barBlur
,
double
overlayBlur
,
SnackbarStatusCallback
snackbarStatus
,
Color
overlayColor
,
Form
userInputForm
,
})
async
{
final
getBar
=
GetBar
(
snackbarStatus:
snackbarStatus
,
titleText:
(
title
==
null
)
?
null
:
titleText
??
Text
(
title
,
style:
TextStyle
(
color:
colorText
??
iconColor
??
Colors
.
black
,
fontWeight:
FontWeight
.
w800
,
fontSize:
16
,
),
),
messageText:
messageText
??
Text
(
message
,
style:
TextStyle
(
color:
colorText
??
iconColor
??
Colors
.
black
,
fontWeight:
FontWeight
.
w300
,
fontSize:
14
,
),
),
snackPosition:
snackPosition
??
SnackPosition
.
TOP
,
borderRadius:
borderRadius
??
15
,
margin:
margin
??
EdgeInsets
.
symmetric
(
horizontal:
10
),
duration:
duration
??
Duration
(
seconds:
3
),
barBlur:
barBlur
??
7.0
,
backgroundColor:
backgroundColor
??
Colors
.
grey
.
withOpacity
(
0.2
),
icon:
icon
,
shouldIconPulse:
shouldIconPulse
??
true
,
maxWidth:
maxWidth
,
padding:
padding
??
EdgeInsets
.
all
(
16
),
borderColor:
borderColor
,
borderWidth:
borderWidth
,
leftBarIndicatorColor:
leftBarIndicatorColor
,
boxShadows:
boxShadows
,
backgroundGradient:
backgroundGradient
,
mainButton:
mainButton
,
onTap:
onTap
,
isDismissible:
isDismissible
??
true
,
dismissDirection:
dismissDirection
??
SnackDismissDirection
.
VERTICAL
,
showProgressIndicator:
showProgressIndicator
??
false
,
progressIndicatorController:
progressIndicatorController
,
progressIndicatorBackgroundColor:
progressIndicatorBackgroundColor
,
progressIndicatorValueColor:
progressIndicatorValueColor
,
snackStyle:
snackStyle
??
SnackStyle
.
FLOATING
,
forwardAnimationCurve:
forwardAnimationCurve
??
Curves
.
easeOutCirc
,
reverseAnimationCurve:
reverseAnimationCurve
??
Curves
.
easeOutCirc
,
animationDuration:
animationDuration
??
Duration
(
seconds:
1
),
overlayBlur:
overlayBlur
??
0.0
,
overlayColor:
overlayColor
??
Colors
.
transparent
,
userInputForm:
userInputForm
);
/// **Navigation.pushAndRemoveUntil()** shortcut .<br><br>
///
/// Push a [page] and pop several pages in the stack
/// until [predicate] returns true. [predicate] is optional
///
/// It has the advantage of not needing context,
/// so you can call from your business logic
///
/// You can set a custom [transition], a [curve] and a transition [duration].
///
/// You can send any type of value to the other route in the [arguments].
///
/// Just like native routing in Flutter, you can push a route
/// as a [fullscreenDialog],
///
/// [predicate] can be used like this:
/// `Get.until((route) => Get.currentRoute == '/home')`so when you get to home page,
/// or also like
/// `Get.until((route) => !Get.isDialogOpen())`, to make sure the dialog
/// is closed
///
/// [id] is for when you are using nested navigation,
/// as explained in documentation
///
/// If you want the same behavior of ios that pops a route when the user drag,
/// you can set [popGesture] to true
///
/// If you're using the [Bindings] api, you must define it here
///
/// By default, GetX will prevent you from push a route that you already in,
/// if you want to push anyway, set [preventDuplicates] to false
Future
<
T
>
offAll
<
T
>(
Widget
page
,
{
RoutePredicate
predicate
,
bool
opaque
=
false
,
bool
popGesture
,
int
id
,
dynamic
arguments
,
Bindings
binding
,
bool
fullscreenDialog
=
false
,
Transition
transition
,
Curve
curve
,
Duration
duration
,
})
{
var
routeName
=
"/
${page.runtimeType.toString()}
"
;
if
(
instantInit
)
{
showSnackbar
(
getBar
);
}
else
{
routing
.
isSnackbar
=
true
;
SchedulerBinding
.
instance
.
addPostFrameCallback
((
_
)
{
showSnackbar
(
getBar
);
});
}
return
global
(
id
)?.
currentState
?.
pushAndRemoveUntil
(
GetPageRoute
(
opaque:
opaque
??
true
,
popGesture:
popGesture
??
defaultPopGesture
,
page:
()
=>
page
,
binding:
binding
,
settings:
RouteSettings
(
arguments:
arguments
),
fullscreenDialog:
fullscreenDialog
,
routeName:
routeName
,
transition:
transition
??
defaultTransition
,
curve:
curve
??
defaultTransitionCurve
,
transitionDuration:
duration
??
defaultTransitionDuration
,
),
predicate
??
(
route
)
=>
false
);
}
void
addPages
(
List
<
GetPage
>
getPages
)
{
...
...
@@ -1024,7 +1033,36 @@ Since version 2.8 it is possible to access the properties
return
_theme
;
}
WidgetsBinding
get
engine
=>
WidgetsBinding
.
instance
;
///The current [WidgetsBinding]
WidgetsBinding
get
engine
{
if
(
WidgetsBinding
.
instance
==
null
)
{
WidgetsFlutterBinding
();
}
return
WidgetsBinding
.
instance
;
}
///The window to which this binding is bound.
Window
get
window
=>
engine
.
window
;
///The number of device pixels for each logical pixel.
double
get
pixelRatio
=>
window
.
devicePixelRatio
;
///The horizontal extent of this size.
double
get
width
=>
window
.
physicalSize
.
width
/
pixelRatio
;
///The vertical extent of this size
double
get
height
=>
window
.
physicalSize
.
height
/
pixelRatio
;
///The distance from the top edge to the first unpadded pixel,
///in physical pixels.
double
get
statusBarHeight
=>
window
.
padding
.
top
;
///The distance from the bottom edge to the first unpadded pixel,
///in physical pixels.
double
get
bottomBarHeight
=>
window
.
padding
.
bottom
;
///The system-reported text scale.
double
get
textScaleFactor
=>
window
.
textScaleFactor
;
/// give access to TextTheme.of(context)
TextTheme
get
textTheme
=>
theme
?.
textTheme
;
...
...
@@ -1036,8 +1074,7 @@ Since version 2.8 it is possible to access the properties
bool
get
isDarkMode
=>
(
theme
.
brightness
==
Brightness
.
dark
);
/// Check if dark mode theme is enable on platform on android Q+
bool
get
isPlatformDarkMode
=>
(
mediaQuery
.
platformBrightness
==
Brightness
.
dark
);
bool
get
isPlatformDarkMode
=>
(
window
.
platformBrightness
==
Brightness
.
dark
);
/// give access to Theme.of(context).iconTheme.color
Color
get
iconColor
=>
theme
?.
iconTheme
?.
color
;
...
...
@@ -1045,11 +1082,11 @@ Since version 2.8 it is possible to access the properties
/// give access to FocusScope.of(context)
FocusNode
get
focusScope
=>
FocusManager
.
instance
.
primaryFocus
;
/// give access to Immutable MediaQuery.of(context).size.height
double
get
height
=>
MediaQuery
.
of
(
context
).
size
.
height
;
// /// give access to Immutable MediaQuery.of(context).size.height
// double get height => MediaQuery.of(context).size.height;
/// give access to Immutable MediaQuery.of(context).size.width
double
get
width
=>
MediaQuery
.
of
(
context
).
size
.
width
;
// /// give access to Immutable MediaQuery.of(context).size.width
// double get width => MediaQuery.of(context).size.width;
GlobalKey
<
NavigatorState
>
get
key
=>
getxController
?.
key
;
...
...
lib/get_rx/src/rx_core/rx_impl.dart
View file @
0986a35
import
'dart:async'
;
import
'dart:collection'
;
import
'package:flutter/foundation.dart'
;
import
'../rx_core/rx_interface.dart'
;
part
'rx_num.dart'
;
...
...
@@ -229,81 +227,6 @@ class Rx<T> extends _RxImpl<T> {
dynamic
toJson
()
=>
(
value
as
dynamic
)?.
toJson
();
}
enum
RxStatus
{
loading
,
error
,
success
}
/// It's Experimental class, the Api can be change
abstract
class
RxState
<
T
>
extends
_RxImpl
<
T
>
{
RxState
(
T
initial
)
:
super
(
initial
)
{
_fillEmptyStatus
();
}
RxStatus
_status
;
bool
get
isNullOrEmpty
{
if
(
_value
==
null
)
return
true
;
dynamic
val
=
_value
;
var
result
=
false
;
if
(
val
is
Iterable
)
{
result
=
val
.
isEmpty
;
}
else
if
(
val
is
String
)
{
result
=
val
.
isEmpty
;
}
else
if
(
val
is
Map
)
{
result
=
val
.
isEmpty
;
}
return
result
;
}
void
_fillEmptyStatus
()
{
_status
=
isNullOrEmpty
?
RxStatus
.
loading
:
RxStatus
.
success
;
}
RxStatus
get
status
{
return
_status
;
}
bool
get
isLoading
=>
_status
==
RxStatus
.
loading
;
bool
get
hasError
=>
_status
==
RxStatus
.
error
;
bool
get
hasData
=>
_status
==
RxStatus
.
success
;
@protected
void
refresh
()
{
subject
.
add
(
_value
);
}
@protected
void
update
(
void
fn
(
T
val
))
{
fn
(
_value
);
subject
.
add
(
_value
);
}
@protected
T
call
([
T
v
])
{
if
(
v
!=
null
)
value
=
v
;
return
value
;
}
@protected
set
value
(
T
val
)
{
if
(
_value
==
val
&&
!
firstRebuild
)
return
;
firstRebuild
=
false
;
_value
=
val
;
subject
.
add
(
_value
);
}
@protected
void
change
(
T
newState
,
{
RxStatus
status
})
{
if
(
status
!=
null
)
{
_status
=
status
;
}
if
(
newState
!=
_value
)
{
value
=
newState
;
}
}
@override
dynamic
toJson
()
=>
(
value
as
dynamic
)?.
toJson
();
}
extension
StringExtension
on
String
{
/// Returns a `RxString` with [this] `String` as initial value.
RxString
get
obs
=>
RxString
(
this
);
...
...
lib/get_state_manager/get_state_manager.dart
View file @
0986a35
...
...
@@ -2,6 +2,7 @@ library get_state_manager;
export
'src/rx_flutter/rx_disposable.dart'
;
export
'src/rx_flutter/rx_getx_widget.dart'
;
export
'src/rx_flutter/rx_notifier.dart'
;
export
'src/rx_flutter/rx_obx_widget.dart'
;
export
'src/rx_flutter/rx_ticket_provider_mixin.dart'
;
export
'src/simple/get_state.dart'
;
...
...
lib/get_state_manager/src/rx_flutter/rx_disposable.dart
View file @
0986a35
...
...
@@ -9,23 +9,37 @@ import '../../../get_instance/src/lifecycle.dart';
/// it is Get.reset().
abstract
class
GetxService
extends
DisposableInterface
with
GetxServiceMixin
{}
abstract
class
DisposableInterface
extends
GetLifeCycle
{
abstract
class
DisposableInterface
with
GetLifeCycle
{
bool
_initialized
=
false
;
/// Checks whether the controller has already been initialized.
bool
get
initialized
=>
_initialized
;
bool
_isClosed
=
false
;
/// Checks whether the controller has already been closed.
bool
get
isClosed
=>
_isClosed
;
DisposableInterface
()
{
onStart
.
callback
=
_onStart
;
onDelete
.
callback
=
_onDelete
;
}
// Internal callback that starts the cycle of this controller.
void
_onStart
()
{
if
(
_initialized
)
return
;
onInit
();
_initialized
=
true
;
SchedulerBinding
.
instance
?.
addPostFrameCallback
((
_
)
=>
onReady
());
}
// Internal callback that starts the cycle of this controller.
void
_onDelete
()
{
if
(
_isClosed
)
return
;
_isClosed
=
true
;
onClose
();
}
/// Called immediately after the widget is allocated in memory.
/// You might use this to initialize something for the controller.
@override
...
...
lib/get_state_manager/src/rx_flutter/rx_notifier.dart
0 → 100644
View file @
0986a35
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'../../../instance_manager.dart'
;
import
'../../get_state_manager.dart'
;
import
'../simple/list_notifier.dart'
;
class
Value
<
T
>
extends
ListNotifier
implements
ValueListenable
<
T
>
{
Value
(
this
.
_value
);
T
get
value
{
notifyChildrens
();
return
_value
;
}
@override
String
toString
()
=>
value
.
toString
();
T
_value
;
set
value
(
T
newValue
)
{
if
(
_value
==
newValue
)
return
;
_value
=
newValue
;
updater
();
}
void
update
(
void
fn
(
T
value
))
{
fn
(
value
);
updater
();
}
}
extension
ReactiveT
<
T
>
on
T
{
Value
<
T
>
get
reactive
=>
Value
<
T
>(
this
);
}
typedef
Condition
=
bool
Function
();
abstract
class
GetNotifier
<
T
>
extends
Value
<
T
>
with
GetLifeCycle
{
GetNotifier
(
T
initial
)
:
super
(
initial
)
{
onStart
.
callback
=
_onStart
;
onDelete
.
callback
=
_onDelete
;
_fillEmptyStatus
();
}
bool
_initialized
=
false
;
/// Checks whether the controller has already been initialized.
bool
get
initialized
=>
_initialized
;
bool
_isClosed
=
false
;
/// Checks whether the controller has already been closed.
bool
get
isClosed
=>
_isClosed
;
// Internal callback that starts the cycle of this controller.
void
_onStart
()
{
if
(
_initialized
)
return
;
onInit
();
_initialized
=
true
;
SchedulerBinding
.
instance
?.
addPostFrameCallback
((
_
)
=>
onReady
());
}
// Internal callback that starts the cycle of this controller.
void
_onDelete
()
{
if
(
_isClosed
)
return
;
_isClosed
=
true
;
onClose
();
}
RxStatus
_status
;
bool
get
isNullOrEmpty
{
if
(
_value
==
null
)
return
true
;
dynamic
val
=
_value
;
var
result
=
false
;
if
(
val
is
Iterable
)
{
result
=
val
.
isEmpty
;
}
else
if
(
val
is
String
)
{
result
=
val
.
isEmpty
;
}
else
if
(
val
is
Map
)
{
result
=
val
.
isEmpty
;
}
return
result
;
}
void
_fillEmptyStatus
()
{
_status
=
isNullOrEmpty
?
RxStatus
.
loading
()
:
RxStatus
.
success
();
}
RxStatus
get
status
{
// notifyChildrens();
return
_status
;
}
Widget
call
(
NotifierBuilder
<
T
>
widget
,
{
Widget
onError
,
Widget
onLoading
})
{
return
SimpleBuilder
(
builder:
(
_
)
{
if
(
status
.
isLoading
)
{
return
onLoading
??
CircularProgressIndicator
();
}
else
if
(
status
.
isError
)
{
return
onError
??
Text
(
'A error occured'
);
}
else
{
if
(
widget
==
null
)
throw
'Widget cannot be null'
;
return
widget
(
value
);
}
});
}
@protected
void
change
(
T
newState
,
{
RxStatus
status
})
{
if
(
status
!=
null
)
{
_status
=
status
;
}
if
(
newState
!=
_value
)
{
value
=
newState
;
}
}
dynamic
toJson
()
=>
(
value
as
dynamic
)?.
toJson
();
}
class
RxStatus
{
final
bool
isLoading
;
final
bool
isError
;
final
bool
isSuccess
;
final
String
errorMessage
;
RxStatus
.
_
({
this
.
isLoading
,
this
.
isError
,
this
.
isSuccess
,
this
.
errorMessage
,
});
factory
RxStatus
.
loading
()
{
return
RxStatus
.
_
(
isLoading:
true
,
isError:
false
,
isSuccess:
false
,
);
}
factory
RxStatus
.
success
()
{
return
RxStatus
.
_
(
isLoading:
false
,
isError:
false
,
isSuccess:
true
,
);
}
factory
RxStatus
.
error
([
String
message
])
{
return
RxStatus
.
_
(
isLoading:
false
,
isError:
true
,
isSuccess:
false
,
errorMessage:
message
,
);
}
}
typedef
NotifierBuilder
<
T
>
=
Widget
Function
(
T
state
);
...
...
lib/get_state_manager/src/simple/get_state.dart
View file @
0986a35
...
...
@@ -4,8 +4,6 @@ import '../../../get_core/get_core.dart';
import
'../../../get_instance/src/get_instance.dart'
;
import
'../../get_state_manager.dart'
;
import
'simple_builder.dart'
;
// Changed to VoidCallback.
//typedef Disposer = void Function();
...
...
@@ -34,12 +32,12 @@ mixin GetStateUpdaterMixin<T extends StatefulWidget> on State<T> {
}
class
GetxController
extends
DisposableInterface
{
final
_updaters
=
HashSet
<
GetStateUpdate
>()
;
final
_updaters
=
<
GetStateUpdate
>[]
;
// final _updatersIds = HashMap<String, StateSetter>(); //<old>
final
_updatersIds
=
HashMap
<
String
,
GetStateUpdate
>();
final
_updatersGroupIds
=
HashMap
<
String
,
HashSe
t
<
GetStateUpdate
>>();
final
_updatersGroupIds
=
HashMap
<
String
,
Lis
t
<
GetStateUpdate
>>();
/// Rebuilds [GetBuilder] each time you call [update()];
/// Can take a List of [ids], that will only update the matching
...
...
@@ -81,7 +79,7 @@ class GetxController extends DisposableInterface {
VoidCallback
addListenerId
(
String
key
,
GetStateUpdate
listener
)
{
// _printCurrentIds();
if
(
_updatersIds
.
containsKey
(
key
))
{
_updatersGroupIds
[
key
]
??=
HashSet
<
GetStateUpdate
>.
identity
()
;
_updatersGroupIds
[
key
]
??=
<
GetStateUpdate
>[]
;
_updatersGroupIds
[
key
].
add
(
listener
);
return
()
{
_updatersGroupIds
[
key
].
remove
(
listener
);
...
...
@@ -254,22 +252,22 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>>
/// This is a experimental feature.
/// Meant to be used with SimpleBuilder, it auto-registers the variable
/// like Rx() does with Obx().
class
Value
<
T
>
extends
GetxController
{
Value
([
this
.
_value
]);
T
_value
;
T
get
value
{
TaskManager
.
instance
.
notify
(
_updaters
);
return
_value
;
}
set
value
(
T
newValue
)
{
if
(
_value
==
newValue
)
return
;
_value
=
newValue
;
update
();
}
}
// class Value<T> extends GetxController {
// Value([this._value]);
// T _value;
// T get value {
// TaskManager.instance.notify(_updaters);
// return _value;
// }
// set value(T newValue) {
// if (_value == newValue) return;
// _value = newValue;
// update();
// }
// }
/// It's Experimental class, the Api can be change
abstract
class
GetState
<
T
>
extends
GetxController
{
...
...
lib/get_state_manager/src/simple/get_view.dart
View file @
0986a35
...
...
@@ -40,7 +40,7 @@ abstract class GetView<T> extends StatelessWidget {
}
abstract
class
GetWidget
<
T
extends
DisposableInterface
>
extends
Get
StatelessWidget
{
extends
StatelessWidget
{
GetWidget
({
Key
key
})
:
super
(
key:
key
);
final
Set
<
T
>
_value
=
<
T
>{};
...
...
@@ -103,7 +103,7 @@ class GetStatelessElement extends ComponentElement {
@override
void
unmount
()
{
widget
?.
controller
?.
on
Clos
e
();
widget
?.
controller
?.
on
Delet
e
();
super
.
unmount
();
}
}
...
...
lib/get_state_manager/src/simple/immutable_state.dart
View file @
0986a35
...
...
@@ -146,3 +146,5 @@
// return widget.builder(controller.state);
// }
//}
...
...
lib/get_state_manager/src/simple/list_notifier.dart
0 → 100644
View file @
0986a35
import
'package:flutter/foundation.dart'
;
import
'simple_builder.dart'
;
class
ListNotifier
implements
Listenable
{
List
<
VoidCallback
>
_listeners
=
<
VoidCallback
>[];
void
updater
()
{
assert
(
_debugAssertNotDisposed
());
for
(
var
element
in
_listeners
)
{
element
();
}
}
bool
_debugAssertNotDisposed
()
{
assert
(()
{
if
(
_listeners
==
null
)
{
throw
FlutterError
(
'''A
$runtimeType
was used after being disposed.
\n
'
Once
you
have
called
dispose
()
on
a
$runtimeType
,
it
can
no
longer
be
used
.
''');
}
return true;
}());
return true;
}
@protected
void notifyChildrens() {
TaskManager.instance.notify(_listeners);
}
bool get hasListeners {
assert(_debugAssertNotDisposed());
return _listeners.isNotEmpty;
}
@override
void addListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
_listeners.add(listener);
}
@override
void removeListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
_listeners.remove(listener);
}
@mustCallSuper
void dispose() {
assert(_debugAssertNotDisposed());
_listeners = null;
}
}
...
...
lib/get_state_manager/src/simple/simple_builder.dart
View file @
0986a35
import
'dart:async'
;
import
'dart:collection'
;
import
'package:flutter/widgets.dart'
;
import
'get_state.dart'
;
...
...
@@ -88,7 +87,7 @@ class SimpleBuilder extends StatefulWidget {
class
_SimpleBuilderState
extends
State
<
SimpleBuilder
>
with
GetStateUpdaterMixin
{
final
HashSet
<
VoidCallback
>
disposers
=
HashSet
<
VoidCallback
>()
;
final
disposers
=
<
VoidCallback
>[]
;
@override
void
dispose
()
{
...
...
@@ -116,13 +115,11 @@ class TaskManager {
static
TaskManager
get
instance
=>
_instance
??=
TaskManager
.
_
();
// StateSetter _setter;//<old>
GetStateUpdate
_setter
;
HashSe
t
<
VoidCallback
>
_remove
;
Lis
t
<
VoidCallback
>
_remove
;
// void notify(HashSet<StateSetter> _updaters) { //<old>
void
notify
(
HashSet
<
GetStateUpdate
>
_updaters
)
{
void
notify
(
List
<
GetStateUpdate
>
_updaters
)
{
if
(
_setter
!=
null
)
{
if
(!
_updaters
.
contains
(
_setter
))
{
_updaters
.
add
(
_setter
);
...
...
@@ -132,8 +129,7 @@ class TaskManager {
}
Widget
exchange
(
HashSet
<
VoidCallback
>
disposers
,
// StateSetter setState, //<old>
List
<
VoidCallback
>
disposers
,
GetStateUpdate
setState
,
Widget
Function
(
BuildContext
)
builder
,
BuildContext
context
,
...
...
test/instance/get_instance_test.dart
View file @
0986a35
...
...
@@ -9,20 +9,29 @@ class Mock {
}
}
class
Controller
{}
class
DisposableController
extends
GetLifeCycle
{
class
DisposableController
with
GetLifeCycle
{
DisposableController
()
{
onStart
.
callback
=
_onStart
;
onDelete
.
callback
=
_onDelete
;
}
// Internal callback that starts the cycle of this controller.
void
_onStart
()
{
if
(
initialized
)
return
;
onInit
();
}
// Internal callback that starts the cycle of this controller.
void
_onDelete
()
{
if
(
isClosed
)
return
;
isClosed
=
true
;
onClose
();
}
bool
initialized
=
false
;
bool
isClosed
=
false
;
void
onInit
()
async
{
initialized
=
true
;
}
...
...
@@ -53,6 +62,17 @@ void main() {
Get
.
reset
();
});
test
(
'Get start and delete called just one time'
,
()
async
{
Get
..
put
(
Controller
())..
put
(
Controller
());
final
controller
=
Get
.
find
<
Controller
>();
expect
(
controller
.
init
,
1
);
Get
..
delete
<
Controller
>()..
delete
<
Controller
>();
expect
(
controller
.
close
,
1
);
Get
.
reset
();
});
test
(
'Get.put tag test'
,
()
async
{
final
instance
=
Get
.
put
<
Controller
>(
Controller
(),
tag:
'one'
);
final
instance2
=
Get
.
put
<
Controller
>(
Controller
(),
tag:
'two'
);
...
...
@@ -128,3 +148,19 @@ void main() {
});
});
}
class
Controller
extends
DisposableController
{
int
init
=
0
;
int
close
=
0
;
@override
void
onInit
()
{
init
++;
super
.
onInit
();
}
@override
void
onClose
()
{
close
++;
super
.
onClose
();
}
}
...
...
Please
register
or
login
to post a comment