Jonny Borges

refactor Binds, remove disposable interface, create a more composable api

Showing 34 changed files with 685 additions and 448 deletions
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'lang/translation_service.dart';
import 'routes/app_pages.dart';
import 'shared/logger/logger_utils.dart';
void main() {
runApp(MyApp());
//MyBindings().dependencies();
runApp(
Binds(
binds: [
Bind.lazyPut(() => Controller()),
Bind.lazyPut(() => Controller2()),
],
child: GetMaterialApp(
home: Home(),
),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
class MyBindings extends Binding {
@override
Widget build(BuildContext context) {
return GetMaterialApp.router(
debugShowCheckedModeBanner: false,
enableLog: true,
logWriterCallback: Logger.write,
// initialRoute: AppPages.INITIAL,
getPages: AppPages.routes,
locale: TranslationService.locale,
fallbackLocale: TranslationService.fallbackLocale,
translations: TranslationService(),
);
List<Bind> dependencies() {
return [
Bind.put(Controller()),
Bind.put(Controller2()),
];
}
}
/// Nav 2 snippet
// void main() {
// runApp(MyApp());
// }
// class MyApp extends StatelessWidget {
// MyApp({Key? key}) : super(key: key);
class Controller extends GetxController {
final count = 0.obs;
void increment() {
count.value++;
update();
}
}
// @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,
// );
// }
// }
class Controller2 extends GetxController {
final count = 0.obs;
// 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'),
// ),
// ),
// ),
// );
// }
// }
Controller2();
void increment() {
count.value++;
update();
}
}
// 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'),
// ),
// ),
// ),
// );
// }
// }
class Home extends ObxStatelessWidget {
const Home({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
print('sasasasa');
return Scaffold(
appBar: AppBar(title: Text("counter")),
body: Builder(builder: (context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Builder(builder: (context) {
print('builder');
final controller = context.listen<Controller>();
return Text('${controller.count.value}');
}),
ElevatedButton(
child: Text('Next Route'),
onPressed: () {
Get.to(() => Second());
},
),
],
),
);
}),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Get.find<Controller>().increment();
},
),
);
}
}
// 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'),
// ),
// ),
// ),
// );
// }
// }
class Second extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.get<Controller2>().increment();
},
),
body: Center(
child: Builder(builder: (context) {
final ctrl = context.listen<Controller2>();
return Text("${ctrl.count}");
}),
),
);
}
}
... ...
import 'package:get/get.dart';
import '../data/home_api_provider.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 Bindings {
class HomeBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<IHomeProvider>(() => HomeProvider());
Get.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find()));
Get.lazyPut(() => HomeController(homeRepository: Get.find()));
List<Bind> dependencies() {
return [
Bind.lazyPut<IHomeProvider>(() => HomeProvider()),
Bind.lazyPut<IHomeRepository>(() => HomeRepository(provider: Get.find())),
Bind.lazyPut(() => HomeController(homeRepository: Get.find())),
];
}
}
... ...
... ... @@ -2,11 +2,13 @@ import 'package:get/get.dart';
import '../controllers/dashboard_controller.dart';
class DashboardBinding extends Bindings {
class DashboardBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<DashboardController>(
() => DashboardController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut<DashboardController>(
() => DashboardController(),
)
];
}
}
... ...
... ... @@ -2,11 +2,13 @@ import 'package:get/get.dart';
import '../controllers/home_controller.dart';
class HomeBinding extends Bindings {
class HomeBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<HomeController>(
() => HomeController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut<HomeController>(
() => HomeController(),
)
];
}
}
... ...
... ... @@ -2,11 +2,11 @@ import 'package:get/get.dart';
import '../controllers/login_controller.dart';
class LoginBinding extends Bindings {
class LoginBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<LoginController>(
() => LoginController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut(() => LoginController()),
];
}
}
... ...
... ... @@ -2,13 +2,15 @@ import 'package:get/get.dart';
import '../controllers/product_details_controller.dart';
class ProductDetailsBinding extends Bindings {
class ProductDetailsBinding extends Binding {
@override
void dependencies() {
Get.create<ProductDetailsController>(
() => ProductDetailsController(
Get.parameters['productId'] ?? '',
),
);
List<Bind> dependencies() {
return [
Bind.create<ProductDetailsController>(
() => ProductDetailsController(
Get.parameters['productId'] ?? '',
),
)
];
}
}
... ...
... ... @@ -2,11 +2,13 @@ import 'package:get/get.dart';
import '../controllers/products_controller.dart';
class ProductsBinding extends Bindings {
class ProductsBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<ProductsController>(
() => ProductsController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut<ProductsController>(
() => ProductsController(),
)
];
}
}
... ...
... ... @@ -2,11 +2,13 @@ import 'package:get/get.dart';
import '../controllers/profile_controller.dart';
class ProfileBinding extends Bindings {
class ProfileBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<ProfileController>(
() => ProfileController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut<ProfileController>(
() => ProfileController(),
)
];
}
}
... ...
... ... @@ -2,11 +2,13 @@ import 'package:get/get.dart';
import '../controllers/root_controller.dart';
class RootBinding extends Bindings {
class RootBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<RootController>(
() => RootController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut<RootController>(
() => RootController(),
)
];
}
}
... ...
... ... @@ -2,11 +2,13 @@ import 'package:get/get.dart';
import '../controllers/settings_controller.dart';
class SettingsBinding extends Bindings {
class SettingsBinding extends Binding {
@override
void dependencies() {
Get.lazyPut<SettingsController>(
() => SettingsController(),
);
List<Bind> dependencies() {
return [
Bind.lazyPut<SettingsController>(
() => SettingsController(),
)
];
}
}
... ...
... ... @@ -46,9 +46,7 @@ class AppPages {
preventDuplicates: true,
name: _Paths.HOME,
page: () => HomeView(),
bindings: [
HomeBinding(),
],
binding: HomeBinding(),
title: null,
children: [
GetPage(
... ...
... ... @@ -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 GetLifeCycleBase {
abstract class GetConnectInterface with GetLifeCycleMixin {
List<GetSocket>? sockets;
GetHttpClient get httpClient;
... ...
... ... @@ -6,8 +6,9 @@ import 'get_instance.dart';
/// instance of Bindings to manage the
/// dependencies() (via Get.put()) for the Route you are opening.
// ignore: one_member_abstracts
abstract class Bindings {
void dependencies();
@Deprecated('Use Binding instead')
abstract class Bindings<T> {
T dependencies();
}
/// Simplifies Bindings generation from a single callback.
... ...
... ... @@ -250,7 +250,7 @@ class GetInstance {
S _startController<S>({String? tag}) {
final key = _getKey(S, tag);
final i = _singl[key]!.getDependency() as S;
if (i is GetLifeCycleBase) {
if (i is GetLifeCycleMixin) {
i.onStart();
if (tag == null) {
Get.log('Instance "$S" has been initialized');
... ... @@ -379,7 +379,7 @@ class GetInstance {
return false;
}
if (i is GetLifeCycleBase) {
if (i is GetLifeCycleMixin) {
i.onDelete();
Get.log('"$newKey" onDelete() called');
}
... ... @@ -452,7 +452,7 @@ class GetInstance {
return;
}
if (i is GetLifeCycleBase) {
if (i is GetLifeCycleMixin) {
i.onDelete();
Get.log('"$newKey" onDelete() called');
}
... ...
... ... @@ -10,12 +10,14 @@ import 'package:flutter/scheduler.dart';
/// }
/// }
/// ```
mixin GetLifeCycleBase {
mixin GetLifeCycleMixin {
/// Called immediately after the widget is allocated in memory.
/// You might use this to initialize something for the controller.
@protected
@mustCallSuper
void onInit() {}
void onInit() {
SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
}
/// Called 1 frame after onInit(). It is the perfect place to enter
/// navigation events, like snackbar, dialogs, or a new route, or
... ... @@ -41,6 +43,7 @@ mixin GetLifeCycleBase {
/// lifetime cycle of the subclass.
// @protected
@mustCallSuper
@nonVirtual
void onStart() {
// _checkIfAlreadyConfigured();
if (_initialized) return;
... ... @@ -55,6 +58,7 @@ mixin GetLifeCycleBase {
// Called when the controller is removed from memory.
@mustCallSuper
@nonVirtual
void onDelete() {
if (_isClosed) return;
_isClosed = true;
... ... @@ -70,13 +74,5 @@ mixin GetLifeCycleBase {
// }
}
abstract class GetLifeCycle with GetLifeCycleBase {
@override
void onInit() {
SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
super.onInit();
}
}
/// Allow track difference between GetxServices and GetxControllers
mixin GetxServiceMixin {}
... ...
... ... @@ -2,6 +2,7 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get_state_manager/src/simple/get_state.dart';
import '../../get_core/get_core.dart';
import '../../get_instance/src/bindings_interface.dart';
... ... @@ -508,7 +509,7 @@ extension GetNavigation on GetInterface {
String? routeName,
bool fullscreenDialog = false,
dynamic arguments,
Bindings? binding,
Binding? binding,
bool preventDuplicates = true,
bool? popGesture,
bool showCupertinoParallax = true,
... ... @@ -894,7 +895,7 @@ you can only use widgets and widget functions here''';
int? id,
String? routeName,
dynamic arguments,
Bindings? binding,
Binding? binding,
bool fullscreenDialog = false,
bool preventDuplicates = true,
Duration? duration,
... ... @@ -960,7 +961,7 @@ you can only use widgets and widget functions here''';
int? id,
String? routeName,
dynamic arguments,
Bindings? binding,
Binding? binding,
bool fullscreenDialog = false,
Transition? transition,
Curve? curve,
... ...
... ... @@ -6,8 +6,7 @@ import 'package:flutter/material.dart';
import '../../../get.dart';
import '../../../get_state_manager/src/simple/list_notifier.dart';
class GetDelegate extends RouterDelegate<GetNavConfig>
with ListenableMixin, ListNotifierMixin {
class GetDelegate extends RouterDelegate<GetNavConfig> with ListNotifierMixin {
final List<GetNavConfig> history = <GetNavConfig>[];
final PopMode backButtonPopMode;
final PreventDuplicateHandlingMode preventDuplicateHandlingMode;
... ...
... ... @@ -44,7 +44,7 @@ class RouterReportManager<T> {
_routesByCreate.clear();
}
void appendRouteByCreate(GetLifeCycleBase i) {
void appendRouteByCreate(GetLifeCycleMixin i) {
_routesByCreate[_current] ??= HashSet<Function>();
// _routesByCreate[Get.reference]!.add(i.onDelete as Function);
_routesByCreate[_current]!.add(i.onDelete);
... ...
... ... @@ -40,7 +40,7 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>
this.barrierDismissible = false,
this.barrierColor,
this.binding,
this.bindings,
this.binds,
this.routeName,
this.page,
this.title,
... ... @@ -61,9 +61,9 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>
final String? routeName;
//final String reference;
final CustomTransition? customTransition;
final Bindings? binding;
final Binding? binding;
final Map<String, String>? parameter;
final List<Bindings>? bindings;
final List<Bind>? binds;
@override
final bool showCupertinoParallax;
... ... @@ -102,18 +102,21 @@ class GetPageRoute<T> extends PageRoute<T> //MaterialPageRoute<T>
final middlewareRunner = MiddlewareRunner(middlewares);
final localbindings = [
if (bindings != null) ...bindings!,
if (binding != null) ...[binding!]
if (binds != null) ...binds!,
if (binding != null) ...binding!.dependencies(),
];
final bindingsToBind = middlewareRunner.runOnBindingsStart(localbindings);
if (bindingsToBind != null) {
for (final binding in bindingsToBind) {
binding.dependencies();
}
}
final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!;
_child = middlewareRunner.runOnPageBuilt(pageToBuild());
if (bindingsToBind != null && bindingsToBind.isNotEmpty) {
_child = Binds(
child: middlewareRunner.runOnPageBuilt(pageToBuild()),
binds: bindingsToBind,
);
} else {
_child = middlewareRunner.runOnPageBuilt(pageToBuild());
}
return _child!;
}
... ...
... ... @@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../../get_core/src/get_main.dart';
import '../../../get_instance/get_instance.dart';
import '../../../get_state_manager/src/simple/get_state.dart';
import '../../get_navigation.dart';
class GetPage<T> extends Page<T> {
... ... @@ -17,8 +17,8 @@ class GetPage<T> extends Page<T> {
final bool maintainState;
final bool opaque;
final double Function(BuildContext context)? gestureWidth;
final Bindings? binding;
final List<Bindings> bindings;
final Binding? binding;
final List<Bind> binds;
final CustomTransition? customTransition;
final Duration? transitionDuration;
final bool fullscreenDialog;
... ... @@ -56,7 +56,7 @@ class GetPage<T> extends Page<T> {
this.transitionDuration,
this.popGesture,
this.binding,
this.bindings = const [],
this.binds = const [],
this.transition,
this.customTransition,
this.fullscreenDialog = false,
... ... @@ -87,8 +87,8 @@ class GetPage<T> extends Page<T> {
Alignment? alignment,
bool? maintainState,
bool? opaque,
Bindings? binding,
List<Bindings>? bindings,
Binding? binding,
List<Bind>? binds,
CustomTransition? customTransition,
Duration? transitionDuration,
bool? fullscreenDialog,
... ... @@ -117,7 +117,7 @@ class GetPage<T> extends Page<T> {
maintainState: maintainState ?? this.maintainState,
opaque: opaque ?? this.opaque,
binding: binding ?? this.binding,
bindings: bindings ?? this.bindings,
binds: binds ?? this.binds,
customTransition: customTransition ?? this.customTransition,
transitionDuration: transitionDuration ?? this.transitionDuration,
fullscreenDialog: fullscreenDialog ?? this.fullscreenDialog,
... ...
// import 'package:flutter/material.dart';
// import 'package:get/get_navigation/src/router_report.dart';
// import 'package:get/instance_manager.dart';
// class Dependencies {
// void lazyPut<S>(InstanceBuilderCallback<S> builder,
// {String? tag, bool fenix = false}) {
// GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
// }
// S call<S>() {
// return find<S>();
// }
// Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
// {String? tag, bool permanent = false}) async =>
// GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
// void create<S>(InstanceBuilderCallback<S> builder,
// {String? tag, bool permanent = true}) =>
// GetInstance().create<S>(builder, tag: tag, permanent: permanent);
// S find<S>({String? tag}) => GetInstance().find<S>(tag: tag);
// S put<S>(S dependency,
// {String? tag,
// bool permanent = false,
// InstanceBuilderCallback<S>? builder}) =>
// GetInstance().put<S>(dependency, tag: tag, permanent: permanent);
// Future<bool> delete<S>({String? tag, bool force = false}) async =>
// GetInstance().delete<S>(tag: tag, force: force);
// Future<void> deleteAll({bool force = false}) async =>
// GetInstance().deleteAll(force: force);
// void reloadAll({bool force = false}) => GetInstance().reloadAll(force: force);
// void reload<S>({String? tag, String? key, bool force = false}) =>
// GetInstance().reload<S>(tag: tag, key: key, force: force);
// bool isRegistered<S>({String? tag}) =>
// GetInstance().isRegistered<S>(tag: tag);
// bool isPrepared<S>({String? tag}) => GetInstance().isPrepared<S>(tag: tag);
// void replace<P>(P child, {String? tag}) {
// final info = GetInstance().getInstanceInfo<P>(tag: tag);
// final permanent = (info.isPermanent ?? false);
// delete<P>(tag: tag, force: permanent);
// put(child, tag: tag, permanent: permanent);
// }
// void lazyReplace<P>(InstanceBuilderCallback<P> builder,
// {String? tag, bool? fenix}) {
// final info = GetInstance().getInstanceInfo<P>(tag: tag);
// final permanent = (info.isPermanent ?? false);
// delete<P>(tag: tag, force: permanent);
// lazyPut(builder, tag: tag, fenix: fenix ?? permanent);
// }
// }
// abstract class Module extends StatefulWidget {
// Module({Key? key}) : super(key: key);
// Widget view(BuildContext context);
// void dependencies(Dependencies i);
// @override
// _ModuleState createState() => _ModuleState();
// }
// class _ModuleState extends State<Module> {
// @override
// void initState() {
// RouterReportManager.instance.reportCurrentRoute(this);
// widget.dependencies(Dependencies());
// super.initState();
// }
// @override
// void dispose() {
// RouterReportManager.instance.reportRouteDispose(this);
// super.dispose();
// }
// @override
// Widget build(BuildContext context) {
// return widget.view(context);
// }
// }
import 'package:flutter/material.dart';
import '../../../instance_manager.dart';
import '../router_report.dart';
class Dependencies {
void lazyPut<S>(InstanceBuilderCallback<S> builder,
{String? tag, bool fenix = false}) {
GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
}
S call<S>() {
return find<S>();
}
Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
{String? tag, bool permanent = false}) async =>
GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
void create<S>(InstanceBuilderCallback<S> builder,
{String? tag, bool permanent = true}) =>
GetInstance().create<S>(builder, tag: tag, permanent: permanent);
S find<S>({String? tag}) => GetInstance().find<S>(tag: tag);
S put<S>(S dependency,
{String? tag,
bool permanent = false,
InstanceBuilderCallback<S>? builder}) =>
GetInstance().put<S>(dependency, tag: tag, permanent: permanent);
Future<bool> delete<S>({String? tag, bool force = false}) async =>
GetInstance().delete<S>(tag: tag, force: force);
Future<void> deleteAll({bool force = false}) async =>
GetInstance().deleteAll(force: force);
void reloadAll({bool force = false}) => GetInstance().reloadAll(force: force);
void reload<S>({String? tag, String? key, bool force = false}) =>
GetInstance().reload<S>(tag: tag, key: key, force: force);
bool isRegistered<S>({String? tag}) =>
GetInstance().isRegistered<S>(tag: tag);
bool isPrepared<S>({String? tag}) => GetInstance().isPrepared<S>(tag: tag);
void replace<P>(P child, {String? tag}) {
final info = GetInstance().getInstanceInfo<P>(tag: tag);
final permanent = (info.isPermanent ?? false);
delete<P>(tag: tag, force: permanent);
put(child, tag: tag, permanent: permanent);
}
void lazyReplace<P>(InstanceBuilderCallback<P> builder,
{String? tag, bool? fenix}) {
final info = GetInstance().getInstanceInfo<P>(tag: tag);
final permanent = (info.isPermanent ?? false);
delete<P>(tag: tag, force: permanent);
lazyPut(builder, tag: tag, fenix: fenix ?? permanent);
}
}
abstract class Module extends StatefulWidget {
Module({Key? key}) : super(key: key);
Widget view(BuildContext context);
void dependencies(Dependencies i);
@override
_ModuleState createState() => _ModuleState();
}
class _ModuleState extends State<Module> {
@override
void initState() {
RouterReportManager.instance.reportCurrentRoute(this);
widget.dependencies(Dependencies());
super.initState();
}
@override
void dispose() {
RouterReportManager.instance.reportRouteDispose(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.view(context);
}
}
... ...
... ... @@ -77,7 +77,7 @@ abstract class _RouteMiddleware {
/// }
/// ```
/// {@end-tool}
List<Bindings>? onBindingsStart(List<Bindings> bindings);
List<Bind>? onBindingsStart(List<Bind> bindings);
/// This function will be called right after the [Bindings] are initialize.
GetPageBuilder? onPageBuildStart(GetPageBuilder page);
... ... @@ -107,7 +107,7 @@ class GetMiddleware implements _RouteMiddleware {
GetPage? onPageCalled(GetPage? page) => page;
@override
List<Bindings>? onBindingsStart(List<Bindings>? bindings) => bindings;
List<Bind>? onBindingsStart(List<Bind>? bindings) => bindings;
@override
GetPageBuilder? onPageBuildStart(GetPageBuilder? page) => page;
... ... @@ -155,7 +155,7 @@ class MiddlewareRunner {
return to;
}
List<Bindings>? runOnBindingsStart(List<Bindings>? bindings) {
List<Bind>? runOnBindingsStart(List<Bind>? bindings) {
_getMiddlewares().forEach((element) {
bindings = element.onBindingsStart(bindings);
});
... ... @@ -212,7 +212,7 @@ class PageRedirect {
gestureWidth: _r.gestureWidth,
customTransition: _r.customTransition,
binding: _r.binding,
bindings: _r.bindings,
binds: _r.binds,
transitionDuration:
_r.transitionDuration ?? Get.defaultTransitionDuration,
transition: _r.transition,
... ... @@ -241,7 +241,7 @@ class PageRedirect {
opaque: _r.opaque,
customTransition: _r.customTransition,
binding: _r.binding,
bindings: _r.bindings,
binds: _r.binds,
transitionDuration:
_r.transitionDuration ?? Get.defaultTransitionDuration,
transition: _r.transition,
... ...
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import '../../../get_instance/src/lifecycle.dart';
/// Unlike GetxController, which serves to control events on each of its pages,
... ... @@ -8,34 +6,6 @@ import '../../../get_instance/src/lifecycle.dart';
/// It is ideal for situations where, once started, that service will
/// remain in memory, such as Auth control for example. Only way to remove
/// it is Get.reset().
abstract class GetxService extends DisposableInterface with GetxServiceMixin {}
abstract class GetxService with GetLifeCycleMixin, GetxServiceMixin {}
abstract class DisposableInterface extends GetLifeCycle {
/// Called immediately after the widget is allocated in memory.
/// You might use this to initialize something for the controller.
@override
@mustCallSuper
void onInit() {
super.onInit();
SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
}
/// Called 1 frame after onInit(). It is the perfect place to enter
/// navigation events, like snackbar, dialogs, or a new route, or
/// async request.
@override
void onReady() {
super.onReady();
}
/// Called before [onDelete] method. [onClose] might be used to
/// dispose resources used by the controller. Like closing events,
/// or streams before the controller is destroyed.
/// Or dispose objects that can potentially create some memory leaks,
/// like TextEditingControllers, AnimationControllers.
/// Might be useful as well to persist some data on disk.
@override
void onClose() {
super.onClose();
}
}
// abstract class DisposableInterface with GetLifeCycleMixin {}
... ...
... ... @@ -2,16 +2,17 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get_instance/src/lifecycle.dart';
import '../../../get_core/get_core.dart';
import '../../../get_instance/src/get_instance.dart';
import '../../../get_rx/src/rx_types/rx_types.dart';
import '../../get_state_manager.dart';
typedef GetXControllerBuilder<T extends DisposableInterface> = Widget Function(
typedef GetXControllerBuilder<T extends GetLifeCycleMixin> = Widget Function(
T controller);
class GetX<T extends DisposableInterface> extends StatefulWidget {
class GetX<T extends GetLifeCycleMixin> extends StatefulWidget {
final GetXControllerBuilder<T> builder;
final bool global;
final bool autoRemove;
... ... @@ -54,7 +55,7 @@ class GetX<T extends DisposableInterface> extends StatefulWidget {
GetXState<T> createState() => GetXState<T>();
}
class GetXState<T extends DisposableInterface> extends State<GetX<T>> {
class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> {
final _observer = RxNotifier();
T? controller;
bool? _isCreator = false;
... ...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import '../../../instance_manager.dart';
import '../../get_state_manager.dart';
... ... @@ -118,15 +117,8 @@ extension ReactiveT<T> on T {
typedef Condition = bool Function();
abstract class GetNotifier<T> extends Value<T> with GetLifeCycleBase {
abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin {
GetNotifier(T initial) : super(initial);
@override
@mustCallSuper
void onInit() {
super.onInit();
SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
}
}
extension StateExt<T> on StateMixin<T> {
... ...
... ... @@ -56,15 +56,6 @@ class _ObxState extends State<ObxWidget> {
RxInterface.notifyChildren(_observer, widget.build);
}
/// The simplest reactive widget in GetX.
///
/// Just pass your Rx variable in the root scope of the callback to have it
... ...
... ... @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import '../../../get_instance/src/lifecycle.dart';
import '../../get_state_manager.dart';
/// Used like `SingleTickerProviderMixin` but only with Get Controllers.
... ... @@ -196,7 +197,7 @@ class _WidgetTicker extends Ticker {
/// }
/// ...
/// ```
mixin SingleGetTickerProviderMixin on DisposableInterface
mixin SingleGetTickerProviderMixin on GetLifeCycleMixin
implements TickerProvider {
@override
Ticker createTicker(TickerCallback onTick) => Ticker(onTick);
... ...
// ignore: prefer_mixin
import 'package:flutter/widgets.dart';
import '../../../instance_manager.dart';
import '../rx_flutter/rx_disposable.dart';
import '../../../instance_manager.dart';
import '../rx_flutter/rx_notifier.dart';
import 'list_notifier.dart';
// ignore: prefer_mixin
abstract class GetxController extends DisposableInterface
with ListenableMixin, ListNotifierMixin {
abstract class GetxController extends Listenable
with GetLifeCycleMixin, ListNotifierMixin {
/// Rebuilds `GetBuilder` each time you call `update()`;
/// Can take a List of [ids], that will only update the matching
/// `GetBuilder( id: )`,
... ... @@ -28,7 +27,7 @@ abstract class GetxController extends DisposableInterface
}
}
mixin ScrollMixin on GetLifeCycleBase {
mixin ScrollMixin on GetLifeCycleMixin {
final ScrollController scroll = ScrollController();
@override
... ... @@ -72,7 +71,7 @@ mixin ScrollMixin on GetLifeCycleBase {
}
}
abstract class RxController extends DisposableInterface {}
abstract class RxController with GetLifeCycleMixin {}
abstract class SuperController<T> extends FullLifeCycleController
with FullLifeCycleMixin, StateMixin<T> {}
... ...
... ... @@ -67,7 +67,7 @@ class GetResponsiveView<T> extends GetView<T> with GetResponsiveMixin {
super(key: key);
}
class GetResponsiveWidget<T extends GetLifeCycleBase?> extends GetWidget<T>
class GetResponsiveWidget<T extends GetLifeCycleMixin> extends GetWidget<T>
with GetResponsiveMixin {
@override
final bool alwaysUseBuilder;
... ...
import 'package:flutter/material.dart';
import '../../../get_instance/src/get_instance.dart';
import '../../../instance_manager.dart';
import '../../get_state_manager.dart';
typedef GetControllerBuilder<T extends DisposableInterface> = Widget Function(
typedef InitBuilder<T> = T Function();
typedef GetControllerBuilder<T extends GetLifeCycleMixin> = Widget Function(
T controller);
extension WatchExt on BuildContext {
T listen<T extends GetxController>() {
return Scope.of(this, rebuild: true);
return Bind.of(this, rebuild: true);
}
}
extension ReadExt on BuildContext {
T find<T extends GetxController>() {
return Scope.of(this);
T get<T extends GetxController>() {
return Bind.of(this);
}
}
// extension FilterExt on BuildContext {
// T filter<T extends GetxController>(Object Function(T value)? filter) {
// return Scope.of(this, filter: filter, rebuild: true);
// return Bind.of(this, filter: filter, rebuild: true);
// }
// }
... ... @@ -33,10 +34,10 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
final bool autoRemove;
final bool assignId;
final Object Function(T value)? filter;
final void Function(ScopeElement<T> state)? initState,
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(Scope<T> oldWidget, ScopeElement<T> state)?
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
final T? init;
... ... @@ -58,8 +59,8 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scope<T>(
init: init,
return BindWrapper(
init: init == null ? null : () => init!,
global: global,
autoRemove: autoRemove,
assignId: assignId,
... ... @@ -71,7 +72,7 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
didChangeDependencies: didChangeDependencies,
didUpdateWidget: didUpdateWidget,
child: Builder(builder: (context) {
final controller = Scope.of<T>(context, rebuild: true);
final controller = Bind.of<T>(context, rebuild: true);
return builder(controller);
}),
);
... ... @@ -79,14 +80,10 @@ class GetBuilder<T extends GetxController> extends StatelessWidget {
}
}
class Scope<T extends GetxController> extends InheritedWidget {
/// Create an inherited widget that updates its dependents when [controller]
/// sends notifications.
///
/// The [child] argument is required
const Scope({
abstract class Bind<T> extends StatelessWidget {
const Bind({
Key? key,
required Widget child,
required this.child,
this.init,
this.global = true,
this.autoRemove = true,
... ... @@ -98,21 +95,9 @@ class Scope<T extends GetxController> extends InheritedWidget {
this.id,
this.didChangeDependencies,
this.didUpdateWidget,
}) : super(key: key, child: child);
}) : super(key: key);
/// The [Listenable] object to which to listen.
///
/// Whenever this object sends change notifications, the dependents of this
/// widget are triggered.
///
/// By default, whenever the [controller] is changed (including when changing to
/// or from null), if the old controller is not equal to the new controller (as
/// determined by the `==` operator), notifications are sent. This behavior
/// can be overridden by overriding [updateShouldNotify].
///
/// While the [controller] is null, no notifications are sent, since the null
/// object cannot itself send notifications.
final T? init;
final InitBuilder<T>? init;
final bool global;
final Object? id;
... ... @@ -120,24 +105,130 @@ class Scope<T extends GetxController> extends InheritedWidget {
final bool autoRemove;
final bool assignId;
final Object Function(T value)? filter;
final void Function(ScopeElement<T> state)? initState,
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(Scope<T> oldWidget, ScopeElement<T> state)?
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
final Widget? child;
static Bind put<S extends GetxController>(S dependency,
{String? tag,
bool permanent = false,
InstanceBuilderCallback<S>? builder}) {
Get.put<S>(dependency, tag: tag, permanent: permanent, builder: builder);
return _FactoryBind<S>(
autoRemove: permanent,
assignId: true,
tag: tag,
);
}
static Bind lazyPut<S>(
InstanceBuilderCallback<S> builder, {
String? tag,
bool fenix = false,
}) {
Get.lazyPut<S>(builder, tag: tag, fenix: fenix);
return _FactoryBind<S>(
tag: tag,
);
}
static Bind create<S extends GetxController>(
InstanceBuilderCallback<S> builder,
{String? tag,
bool permanent = true}) {
Get.create<S>(builder, tag: tag, permanent: permanent);
return _FactoryBind<S>(
tag: tag,
);
}
static S find<S>({String? tag}) => GetInstance().find<S>(tag: tag);
static Future<bool> delete<S>({String? tag, bool force = false}) async =>
GetInstance().delete<S>(tag: tag, force: force);
static Future<void> deleteAll({bool force = false}) async =>
GetInstance().deleteAll(force: force);
static void reloadAll({bool force = false}) =>
GetInstance().reloadAll(force: force);
static void reload<S>({String? tag, String? key, bool force = false}) =>
GetInstance().reload<S>(tag: tag, key: key, force: force);
static bool isRegistered<S>({String? tag}) =>
GetInstance().isRegistered<S>(tag: tag);
static bool isPrepared<S>({String? tag}) =>
GetInstance().isPrepared<S>(tag: tag);
static void replace<P>(P child, {String? tag}) {
final info = GetInstance().getInstanceInfo<P>(tag: tag);
final permanent = (info.isPermanent ?? false);
delete<P>(tag: tag, force: permanent);
GetInstance().put(child, tag: tag, permanent: permanent);
}
static void lazyReplace<P>(InstanceBuilderCallback<P> builder,
{String? tag, bool? fenix}) {
final info = GetInstance().getInstanceInfo<P>(tag: tag);
final permanent = (info.isPermanent ?? false);
delete<P>(tag: tag, force: permanent);
GetInstance().lazyPut(builder, tag: tag, fenix: fenix ?? permanent);
}
factory Bind.builder({
Widget? child,
InitBuilder<T>? init,
bool global = true,
bool autoRemove = true,
bool assignId = false,
Object Function(T value)? filter,
String? tag,
Object? id,
void Function(BindElement<T> state)? initState,
void Function(BindElement<T> state)? dispose,
void Function(BindElement<T> state)? didChangeDependencies,
void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget,
}) =>
_FactoryBind<T>(
// key: key,
init: init,
global: global,
autoRemove: autoRemove,
assignId: assignId,
initState: initState,
filter: filter,
tag: tag,
dispose: dispose,
id: id,
didChangeDependencies: didChangeDependencies,
didUpdateWidget: didUpdateWidget,
child: child,
);
static T of<T extends GetxController>(
BuildContext context, {
bool rebuild = false,
// Object Function(T value)? filter,
}) {
final inheritedElement = context
.getElementForInheritedWidgetOfExactType<Scope<T>>() as ScopeElement<T>;
final inheritedElement =
context.getElementForInheritedWidgetOfExactType<BindWrapper<T>>()
as BindElement<T>?;
if (inheritedElement == null) {
throw BindError(controller: '$T', tag: null);
}
if (rebuild) {
// var newFilter = filter?.call(inheritedElement.controller!);
// if (newFilter != null) {
// context.dependOnInheritedElement(inheritedElement, aspect: newFilter);
// context.dependOnInheritedElement(inheritedElement, aspect: newFilter);
// } else {
context.dependOnInheritedElement(inheritedElement);
// }
... ... @@ -145,15 +236,159 @@ class Scope<T extends GetxController> extends InheritedWidget {
var widget = inheritedElement.controller;
if (widget == null) {
throw 'Error: Could not find the correct dependency.';
} else {
return widget;
}
return widget;
}
@factory
Bind<T> _copyWithChild(Widget child);
}
class _FactoryBind<T> extends Bind<T> {
@override
final InitBuilder<T>? init;
@override
final bool global;
@override
final Object? id;
@override
final String? tag;
@override
final bool autoRemove;
@override
final bool assignId;
@override
final Object Function(T value)? filter;
@override
bool updateShouldNotify(Scope<T> oldWidget) {
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
@override
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
@override
final Widget? child;
const _FactoryBind({
Key? key,
this.child,
this.init,
this.global = true,
this.autoRemove = true,
this.assignId = false,
this.initState,
this.filter,
this.tag,
this.dispose,
this.id,
this.didChangeDependencies,
this.didUpdateWidget,
}) : super(key: key, child: child);
@override
Bind<T> _copyWithChild(Widget child) {
return Bind<T>.builder(
init: init,
global: global,
autoRemove: autoRemove,
assignId: assignId,
initState: initState,
filter: filter,
tag: tag,
dispose: dispose,
id: id,
didChangeDependencies: didChangeDependencies,
didUpdateWidget: didUpdateWidget,
child: child,
);
}
@override
Widget build(BuildContext context) {
return BindWrapper<T>(
init: init,
global: global,
autoRemove: autoRemove,
assignId: assignId,
initState: initState,
filter: filter,
tag: tag,
dispose: dispose,
id: id,
didChangeDependencies: didChangeDependencies,
didUpdateWidget: didUpdateWidget,
child: child!,
);
}
}
class Binds extends StatelessWidget {
final List<Bind<dynamic>> binds;
final Widget child;
Binds({
Key? key,
required this.binds,
required this.child,
}) : assert(binds.isNotEmpty),
super(key: key);
@override
Widget build(BuildContext context) =>
binds.reversed.fold(child, (acc, e) => e._copyWithChild(acc));
}
class BindWrapper<T> extends InheritedWidget {
/// Create an inherited widget that updates its dependents when [controller]
/// sends notifications.
///
/// The [child] argument is required
const BindWrapper({
Key? key,
required Widget child,
this.init,
this.global = true,
this.autoRemove = true,
this.assignId = false,
this.initState,
this.filter,
this.tag,
this.dispose,
this.id,
this.didChangeDependencies,
this.didUpdateWidget,
}) : super(key: key, child: child);
/// The [Listenable] object to which to listen.
///
/// Whenever this object sends change notifications, the dependents of this
/// widget are triggered.
///
/// By default, whenever the [controller] is changed (including when changing to
/// or from null), if the old controller is not equal to the new controller (as
/// determined by the `==` operator), notifications are sent. This behavior
/// can be overridden by overriding [updateShouldNotify].
///
/// While the [controller] is null, no notifications are sent, since the null
/// object cannot itself send notifications.
final InitBuilder<T>? init;
final bool global;
final Object? id;
final String? tag;
final bool autoRemove;
final bool assignId;
final Object Function(T value)? filter;
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
@override
bool updateShouldNotify(BindWrapper<T> oldWidget) {
return oldWidget.id != id ||
oldWidget.global != global ||
oldWidget.autoRemove != autoRemove ||
... ... @@ -161,18 +396,37 @@ class Scope<T extends GetxController> extends InheritedWidget {
}
@override
InheritedElement createElement() => ScopeElement<T>(this);
InheritedElement createElement() => BindElement<T>(this);
}
/// The ScopeElement is responsible for injecting dependencies into the widget
/// The BindElement is responsible for injecting dependencies into the widget
/// tree so that they can be observed
class ScopeElement<T extends GetxController> extends InheritedElement {
ScopeElement(Scope<T> widget) : super(widget) {
class BindElement<T> extends InheritedElement {
BindElement(BindWrapper<T> widget) : super(widget) {
initState();
}
T? controller;
InitBuilder<T>? _controllerBuilder;
T? _controller;
T get controller {
print('get controller $T');
if (_controller == null) {
_controller = _controllerBuilder?.call();
_subscribeToController();
if (_controller == null) {
throw BindError(controller: T, tag: widget.tag);
}
return _controller!;
} else {
return _controller!;
}
}
bool? _isCreator = false;
bool? _needStart = false;
bool _wasStarted = false;
VoidCallback? _remove;
Object? _filter;
... ... @@ -188,42 +442,50 @@ class ScopeElement<T extends GetxController> extends InheritedElement {
} else {
_isCreator = false;
}
controller = GetInstance().find<T>(tag: widget.tag);
_controllerBuilder = () => GetInstance().find<T>(tag: widget.tag);
} else {
controller = widget.init;
_controllerBuilder = widget.init;
_isCreator = true;
GetInstance().put<T>(controller!, tag: widget.tag);
GetInstance().lazyPut<T>(_controllerBuilder!, tag: widget.tag);
}
} else {
controller = widget.init;
_controllerBuilder = widget.init;
_isCreator = true;
controller?.onStart();
_needStart = true;
}
if (widget.filter != null) {
_filter = widget.filter!(controller!);
}
_subscribeToController();
}
/// Register to listen Controller's events.
/// It gets a reference to the remove() callback, to delete the
/// setState "link" from the Controller.
void _subscribeToController() {
_remove?.call();
_remove = (widget.id == null)
? controller?.addListener(
_filter != null ? _filterUpdate : getUpdate,
)
: controller?.addListenerId(
widget.id,
_filter != null ? _filterUpdate : getUpdate,
);
if (widget.filter != null) {
_filter = widget.filter!(_controller!);
}
final filter = _filter != null ? _filterUpdate : getUpdate;
final localController = _controller;
if (_needStart == true && localController is GetLifeCycleMixin) {
localController.onStart();
_needStart = false;
_wasStarted = true;
}
if (localController is GetxController) {
_remove?.call();
_remove = (widget.id == null)
? localController.addListener(filter)
: localController.addListenerId(widget.id, filter);
} else if (localController is Listenable) {
_remove?.call();
localController.addListener(filter);
_remove = () => localController.removeListener(filter);
}
}
void _filterUpdate() {
var newFilter = widget.filter!(controller!);
var newFilter = widget.filter!(_controller!);
if (newFilter != _filter) {
_filter = newFilter;
getUpdate();
... ... @@ -239,23 +501,25 @@ class ScopeElement<T extends GetxController> extends InheritedElement {
}
_remove?.call();
controller = null;
_controller = null;
_isCreator = null;
_remove = null;
_filter = null;
_needStart = null;
_controllerBuilder = null;
_controller = null;
}
@override
Scope<T> get widget => super.widget as Scope<T>;
BindWrapper<T> get widget => super.widget as BindWrapper<T>;
var _dirty = false;
@override
void update(Scope<T> newWidget) {
void update(BindWrapper<T> newWidget) {
final oldNotifier = widget.id;
final newNotifier = newWidget.id;
if (oldNotifier != newNotifier) {
if (oldNotifier != newNotifier && _wasStarted) {
_subscribeToController();
}
widget.didUpdateWidget?.call(widget, this);
... ... @@ -282,7 +546,7 @@ class ScopeElement<T extends GetxController> extends InheritedElement {
}
@override
void notifyClients(Scope<T> oldWidget) {
void notifyClients(BindWrapper<T> oldWidget) {
super.notifyClients(oldWidget);
_dirty = false;
}
... ... @@ -293,3 +557,32 @@ class ScopeElement<T extends GetxController> extends InheritedElement {
super.unmount();
}
}
class BindError<T> extends Error {
/// The type of the class the user tried to retrieve
final T controller;
final String? tag;
/// Creates a [BindError]
BindError({required this.controller, required this.tag});
@override
String toString() {
if (controller == 'dynamic') {
return '''Error: please specify type [<T>] when calling context.listen<T>() or context.find<T>() method.''';
}
return '''Error: No Bind<$controller> ancestor found. To fix this, please add a Bind<$controller> widget ancestor to the current context.
''';
}
}
/// [Binding] should be extended.
/// When using `GetMaterialApp`, all `GetPage`s and navigation
/// methods (like Get.to()) have a `binding` property that takes an
/// instance of Bindings to manage the
/// dependencies() (via Get.put()) for the Route you are opening.
// ignore: one_member_abstracts
abstract class Binding {
List<Bind> dependencies();
}
... ...
... ... @@ -47,7 +47,7 @@ abstract class GetView<T> extends StatelessWidget {
/// GetWidget is perfect to multiples instance of a same controller. Each
/// GetWidget will have your own controller, and will be call events as `onInit`
/// and `onClose` when the controller get in/get out on memory.
abstract class GetWidget<S extends GetLifeCycleBase?> extends GetWidgetCache {
abstract class GetWidget<S extends GetLifeCycleMixin> extends GetWidgetCache {
const GetWidget({Key? key}) : super(key: key);
@protected
... ... @@ -57,7 +57,7 @@ abstract class GetWidget<S extends GetLifeCycleBase?> extends GetWidgetCache {
// static final _cache = <GetWidget, GetLifeCycleBase>{};
static final _cache = Expando<GetLifeCycleBase>();
static final _cache = Expando<GetLifeCycleMixin>();
@protected
Widget build(BuildContext context);
... ... @@ -66,7 +66,7 @@ abstract class GetWidget<S extends GetLifeCycleBase?> extends GetWidgetCache {
WidgetCache createWidgetCache() => _GetCache<S>();
}
class _GetCache<S extends GetLifeCycleBase?> extends WidgetCache<GetWidget<S>> {
class _GetCache<S extends GetLifeCycleMixin> extends WidgetCache<GetWidget<S>> {
S? _controller;
bool _isCreator = false;
InstanceInfo? info;
... ... @@ -88,7 +88,7 @@ class _GetCache<S extends GetLifeCycleBase?> extends WidgetCache<GetWidget<S>> {
void onClose() {
if (_isCreator) {
Get.asap(() {
widget!.controller!.onDelete();
widget!.controller.onDelete();
Get.log('"${widget!.controller.runtimeType}" onClose() called');
Get.log('"${widget!.controller.runtimeType}" deleted from memory');
GetWidget._cache[widget!] = null;
... ...
... ... @@ -9,10 +9,10 @@ typedef Disposer = void Function();
// if it brings overhead the extra call,
typedef GetStateUpdate = void Function();
class ListNotifier extends Listenable with ListenableMixin, ListNotifierMixin {}
class ListNotifier extends Listenable with ListNotifierMixin {}
mixin ListenableMixin implements Listenable {}
mixin ListNotifierMixin on ListenableMixin {
//mixin ListenableMixin implements Listenable {}
mixin ListNotifierMixin on Listenable {
// int _version = 0;
// int _microtask = 0;
... ...
... ... @@ -8,10 +8,10 @@ class MixinBuilder<T extends GetxController> extends StatelessWidget {
final bool global;
final String? id;
final bool autoRemove;
final void Function(ScopeElement<T> state)? initState,
final void Function(BindElement<T> state)? initState,
dispose,
didChangeDependencies;
final void Function(Scope<T> oldWidget, ScopeElement<T> state)?
final void Function(BindWrapper<T> oldWidget, BindElement<T> state)?
didUpdateWidget;
final T? init;
... ...
... ... @@ -12,7 +12,7 @@ class Mock {
}
}
abstract class MyController extends GetLifeCycle {}
abstract class MyController with GetLifeCycleMixin {}
class DisposableController extends MyController {}
... ...