new change to use intaleq_map sdk 04-16-4
This commit is contained in:
4
packages/get/lib/get_instance/get_instance.dart
Normal file
4
packages/get/lib/get_instance/get_instance.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
export 'src/bindings_interface.dart';
|
||||
export 'src/extension_instance.dart';
|
||||
export 'src/get_instance.dart';
|
||||
export 'src/lifecycle.dart';
|
||||
65
packages/get/lib/get_instance/src/bindings_interface.dart
Normal file
65
packages/get/lib/get_instance/src/bindings_interface.dart
Normal file
@@ -0,0 +1,65 @@
|
||||
import 'get_instance.dart';
|
||||
|
||||
/// [Bindings] should be extended or implemented.
|
||||
/// 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 Bindings {
|
||||
void dependencies();
|
||||
}
|
||||
|
||||
/// Simplifies Bindings generation from a single callback.
|
||||
/// To avoid the creation of a custom Binding instance per route.
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// GetPage(
|
||||
/// name: '/',
|
||||
/// page: () => Home(),
|
||||
/// // This might cause you an error.
|
||||
/// // binding: BindingsBuilder(() => Get.put(HomeController())),
|
||||
/// binding: BindingsBuilder(() { Get.put(HomeController(); })),
|
||||
/// // Using .lazyPut() works fine.
|
||||
/// // binding: BindingsBuilder(() => Get.lazyPut(() => HomeController())),
|
||||
/// ),
|
||||
/// ```
|
||||
class BindingsBuilder<T> extends Bindings {
|
||||
/// Register your dependencies in the [builder] callback.
|
||||
final BindingBuilderCallback builder;
|
||||
|
||||
/// Shortcut to register 1 Controller with Get.put(),
|
||||
/// Prevents the issue of the fat arrow function with the constructor.
|
||||
/// BindingsBuilder(() => Get.put(HomeController())),
|
||||
///
|
||||
/// Sample:
|
||||
/// ```
|
||||
/// GetPage(
|
||||
/// name: '/',
|
||||
/// page: () => Home(),
|
||||
/// binding: BindingsBuilder.put(() => HomeController()),
|
||||
/// ),
|
||||
/// ```
|
||||
factory BindingsBuilder.put(InstanceBuilderCallback<T> builder,
|
||||
{String? tag, bool permanent = false}) {
|
||||
return BindingsBuilder(
|
||||
() => GetInstance().put<T>(builder(), tag: tag, permanent: permanent));
|
||||
}
|
||||
|
||||
/// WARNING: don't use `()=> Get.put(Controller())`,
|
||||
/// if only passing 1 callback use `BindingsBuilder.put(Controller())`
|
||||
/// or `BindingsBuilder(()=> Get.lazyPut(Controller()))`
|
||||
BindingsBuilder(this.builder);
|
||||
|
||||
@override
|
||||
void dependencies() {
|
||||
builder();
|
||||
}
|
||||
}
|
||||
|
||||
// abstract class INavigation {}
|
||||
// typedef Snack = Function();
|
||||
// typedef Modal = Function();
|
||||
// typedef Route = Function();
|
||||
typedef BindingBuilderCallback = void Function();
|
||||
160
packages/get/lib/get_instance/src/extension_instance.dart
Normal file
160
packages/get/lib/get_instance/src/extension_instance.dart
Normal file
@@ -0,0 +1,160 @@
|
||||
import '../../route_manager.dart';
|
||||
import 'get_instance.dart';
|
||||
|
||||
extension Inst on GetInterface {
|
||||
/// Creates a new Instance<S> lazily from the `<S>builder()` callback.
|
||||
///
|
||||
/// The first time you call `Get.find()`, the `builder()` callback will create
|
||||
/// the Instance and persisted as a Singleton (like you would use
|
||||
/// `Get.put()`).
|
||||
///
|
||||
/// Using `Get.smartManagement` as [SmartManagement.keepFactory] has
|
||||
/// the same outcome
|
||||
/// as using `fenix:true` :
|
||||
/// The internal register of `builder()` will remain in memory to recreate
|
||||
/// the Instance if the Instance has been removed with `Get.delete()`.
|
||||
/// Therefore, future calls to `Get.find()` will return the same Instance.
|
||||
///
|
||||
/// If you need to make use of GetxController's life-cycle
|
||||
/// (`onInit(), onStart(), onClose()`)
|
||||
/// [fenix] is a great choice to mix with `GetBuilder` and `GetX` widgets,
|
||||
/// and/or [GetMaterialApp] Navigation.
|
||||
///
|
||||
/// You could use `Get.lazyPut(fenix:true)` in your app's `main()` instead of
|
||||
/// `Bindings` for each [GetPage].
|
||||
/// And the memory management will be similar.
|
||||
///
|
||||
/// Subsequent calls to `Get.lazyPut` with the same parameters
|
||||
/// (`<S>` and optionally [tag] will **not** override the original).
|
||||
void lazyPut<S>(InstanceBuilderCallback<S> builder,
|
||||
{String? tag, bool fenix = false}) {
|
||||
GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
|
||||
}
|
||||
|
||||
// void printInstanceStack() {
|
||||
// GetInstance().printInstanceStack();
|
||||
// }
|
||||
|
||||
/// async version of `Get.put()`.
|
||||
/// Awaits for the resolution of the Future from `builder()`parameter and
|
||||
/// stores the Instance returned.
|
||||
Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
|
||||
{String? tag, bool permanent = false}) async =>
|
||||
GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
|
||||
|
||||
/// Creates a new Class Instance [S] from the builder callback[S].
|
||||
/// Every time `find<S>()` is used, it calls the builder method to generate
|
||||
/// a new Instance [S].
|
||||
/// It also registers each `instance.onClose()` with the current
|
||||
/// Route `GetConfig.currentRoute` to keep the lifecycle active.
|
||||
/// Is important to know that the instances created are only stored per Route.
|
||||
/// So, if you call `Get.delete<T>()` the "instance factory" used in this
|
||||
/// method (`Get.create<T>()`) will be removed, but NOT the instances
|
||||
/// already created by it.
|
||||
/// Uses `tag` as the other methods.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```create(() => Repl());
|
||||
/// Repl a = find();
|
||||
/// Repl b = find();
|
||||
/// print(a==b); (false)```
|
||||
void create<S>(InstanceBuilderCallback<S> builder,
|
||||
{String? tag, bool permanent = true}) =>
|
||||
GetInstance().create<S>(builder, tag: tag, permanent: permanent);
|
||||
|
||||
/// Finds a Instance of the required Class `<S>`(or [tag])
|
||||
/// In the case of using `Get.create()`, it will generate an Instance
|
||||
/// each time you call `Get.find()`.
|
||||
S find<S>({String? tag}) => GetInstance().find<S>(tag: tag);
|
||||
|
||||
/// Injects an `Instance<S>` in memory.
|
||||
///
|
||||
/// No need to define the generic type `<[S]>` as it's inferred
|
||||
/// from the [dependency] parameter.
|
||||
///
|
||||
/// - [dependency] The Instance to be injected.
|
||||
/// - [tag] optionally, use a [tag] as an "id" to create multiple records
|
||||
/// of the same `Type<S>` the [tag] does **not** conflict with the same tags
|
||||
/// used by other dependencies Types.
|
||||
/// - [permanent] keeps the Instance in memory and persist it,
|
||||
/// not following `Get.smartManagement`
|
||||
/// rules. Although, can be removed by `GetInstance.reset()`
|
||||
/// and `Get.delete()`
|
||||
/// - [builder] If defined, the [dependency] must be returned from here
|
||||
S put<S>(S dependency,
|
||||
{String? tag,
|
||||
bool permanent = false,
|
||||
InstanceBuilderCallback<S>? builder}) =>
|
||||
GetInstance().put<S>(dependency, tag: tag, permanent: permanent);
|
||||
|
||||
/// Clears all registered instances (and/or tags).
|
||||
/// Even the persistent ones.
|
||||
///
|
||||
/// - `clearFactory` clears the callbacks registered by `Get.lazyPut()`
|
||||
/// - `clearRouteBindings` clears Instances associated with Routes when using
|
||||
/// [GetMaterialApp].
|
||||
// bool reset(
|
||||
// {@deprecated bool clearFactory = true,
|
||||
// @deprecated bool clearRouteBindings = true}) =>
|
||||
// GetInstance().reset(
|
||||
// // ignore: deprecated_member_use_from_same_package
|
||||
// clearFactory: clearFactory,
|
||||
// // ignore: deprecated_member_use_from_same_package
|
||||
// clearRouteBindings: clearRouteBindings);
|
||||
|
||||
/// Deletes the `Instance<S>`, cleaning the memory and closes any open
|
||||
/// controllers (`DisposableInterface`).
|
||||
///
|
||||
/// - [tag] Optional "tag" used to register the Instance
|
||||
/// - [force] Will delete an Instance even if marked as `permanent`.
|
||||
Future<bool> delete<S>({String? tag, bool force = false}) async =>
|
||||
GetInstance().delete<S>(tag: tag, force: force);
|
||||
|
||||
/// Deletes all Instances, cleaning the memory and closes any open
|
||||
/// controllers (`DisposableInterface`).
|
||||
///
|
||||
/// - [force] Will delete the Instances even if marked as `permanent`.
|
||||
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);
|
||||
|
||||
/// Checks if a Class `Instance<S>` (or [tag]) is registered in memory.
|
||||
/// - [tag] optional, if you use a [tag] to register the Instance.
|
||||
bool isRegistered<S>({String? tag}) =>
|
||||
GetInstance().isRegistered<S>(tag: tag);
|
||||
|
||||
/// Checks if an `Instance<S>` (or [tag]) returned from a factory builder
|
||||
/// `Get.lazyPut()`, is registered in memory.
|
||||
/// - [tag] optional, if you use a [tag] to register the Instance.
|
||||
bool isPrepared<S>({String? tag}) => GetInstance().isPrepared<S>(tag: tag);
|
||||
|
||||
/// Replace a parent instance of a class in dependency management
|
||||
/// with a [child] instance
|
||||
/// - [tag] optional, if you use a [tag] to register the Instance.
|
||||
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);
|
||||
}
|
||||
|
||||
/// Replaces a parent instance with a new Instance<P> lazily from the
|
||||
/// `<P>builder()` callback.
|
||||
/// - [tag] optional, if you use a [tag] to register the Instance.
|
||||
/// - [fenix] optional
|
||||
///
|
||||
/// Note: if fenix is not provided it will be set to true if
|
||||
/// the parent instance was 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);
|
||||
}
|
||||
}
|
||||
551
packages/get/lib/get_instance/src/get_instance.dart
Normal file
551
packages/get/lib/get_instance/src/get_instance.dart
Normal file
@@ -0,0 +1,551 @@
|
||||
import 'dart:async';
|
||||
|
||||
import '../../get_core/get_core.dart';
|
||||
import '../../get_navigation/src/router_report.dart';
|
||||
import 'lifecycle.dart';
|
||||
|
||||
class InstanceInfo {
|
||||
final bool? isPermanent;
|
||||
final bool? isSingleton;
|
||||
bool get isCreate => !isSingleton!;
|
||||
final bool isRegistered;
|
||||
final bool isPrepared;
|
||||
final bool? isInit;
|
||||
const InstanceInfo({
|
||||
required this.isPermanent,
|
||||
required this.isSingleton,
|
||||
required this.isRegistered,
|
||||
required this.isPrepared,
|
||||
required this.isInit,
|
||||
});
|
||||
}
|
||||
|
||||
class GetInstance {
|
||||
factory GetInstance() => _getInstance ??= const GetInstance._();
|
||||
|
||||
const GetInstance._();
|
||||
|
||||
static GetInstance? _getInstance;
|
||||
|
||||
T call<T>() => find<T>();
|
||||
|
||||
/// Holds references to every registered Instance when using
|
||||
/// `Get.put()`
|
||||
static final Map<String, _InstanceBuilderFactory> _singl = {};
|
||||
|
||||
/// Holds a reference to every registered callback when using
|
||||
/// `Get.lazyPut()`
|
||||
// static final Map<String, _Lazy> _factory = {};
|
||||
|
||||
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.
|
||||
Future<S> putAsync<S>(
|
||||
AsyncInstanceBuilderCallback<S> builder, {
|
||||
String? tag,
|
||||
bool permanent = false,
|
||||
}) async {
|
||||
return put<S>(await builder(), tag: tag, permanent: permanent);
|
||||
}
|
||||
|
||||
/// Injects an instance `<S>` in memory to be globally accessible.
|
||||
///
|
||||
/// No need to define the generic type `<S>` as it's inferred from
|
||||
/// the [dependency]
|
||||
///
|
||||
/// - [dependency] The Instance to be injected.
|
||||
/// - [tag] optionally, use a [tag] as an "id" to create multiple records of
|
||||
/// the same Type<[S]>
|
||||
/// - [permanent] keeps the Instance in memory, not following
|
||||
/// `Get.smartManagement` rules.
|
||||
S put<S>(
|
||||
S dependency, {
|
||||
String? tag,
|
||||
bool permanent = false,
|
||||
@deprecated InstanceBuilderCallback<S>? builder,
|
||||
}) {
|
||||
_insert(
|
||||
isSingleton: true,
|
||||
name: tag,
|
||||
permanent: permanent,
|
||||
builder: builder ?? (() => dependency));
|
||||
return find<S>(tag: tag);
|
||||
}
|
||||
|
||||
/// Creates a new Instance<S> lazily from the `<S>builder()` callback.
|
||||
///
|
||||
/// The first time you call `Get.find()`, the `builder()` callback will create
|
||||
/// the Instance and persisted as a Singleton (like you would
|
||||
/// use `Get.put()`).
|
||||
///
|
||||
/// Using `Get.smartManagement` as [SmartManagement.keepFactory] has
|
||||
/// the same outcome as using `fenix:true` :
|
||||
/// The internal register of `builder()` will remain in memory to recreate
|
||||
/// the Instance if the Instance has been removed with `Get.delete()`.
|
||||
/// Therefore, future calls to `Get.find()` will return the same Instance.
|
||||
///
|
||||
/// If you need to make use of GetxController's life-cycle
|
||||
/// (`onInit(), onStart(), onClose()`) [fenix] is a great choice to mix with
|
||||
/// `GetBuilder()` and `GetX()` widgets, and/or `GetMaterialApp` Navigation.
|
||||
///
|
||||
/// You could use `Get.lazyPut(fenix:true)` in your app's `main()` instead
|
||||
/// of `Bindings()` for each `GetPage`.
|
||||
/// And the memory management will be similar.
|
||||
///
|
||||
/// Subsequent calls to `Get.lazyPut()` with the same parameters
|
||||
/// (<[S]> and optionally [tag] will **not** override the original).
|
||||
void lazyPut<S>(
|
||||
InstanceBuilderCallback<S> builder, {
|
||||
String? tag,
|
||||
bool? fenix,
|
||||
bool permanent = false,
|
||||
}) {
|
||||
_insert(
|
||||
isSingleton: true,
|
||||
name: tag,
|
||||
permanent: permanent,
|
||||
builder: builder,
|
||||
fenix: fenix ?? Get.smartManagement == SmartManagement.keepFactory,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a new Class Instance [S] from the builder callback[S].
|
||||
/// Every time [find]<[S]>() is used, it calls the builder method to generate
|
||||
/// a new Instance [S].
|
||||
/// It also registers each `instance.onClose()` with the current
|
||||
/// Route `Get.reference` to keep the lifecycle active.
|
||||
/// Is important to know that the instances created are only stored per Route.
|
||||
/// So, if you call `Get.delete<T>()` the "instance factory" used in this
|
||||
/// method (`Get.create<T>()`) will be removed, but NOT the instances
|
||||
/// already created by it.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```create(() => Repl());
|
||||
/// Repl a = find();
|
||||
/// Repl b = find();
|
||||
/// print(a==b); (false)```
|
||||
void create<S>(
|
||||
InstanceBuilderCallback<S> builder, {
|
||||
String? tag,
|
||||
bool permanent = true,
|
||||
}) {
|
||||
_insert(
|
||||
isSingleton: false,
|
||||
name: tag,
|
||||
builder: builder,
|
||||
permanent: permanent,
|
||||
);
|
||||
}
|
||||
|
||||
/// Injects the Instance [S] builder into the `_singleton` HashMap.
|
||||
void _insert<S>({
|
||||
bool? isSingleton,
|
||||
String? name,
|
||||
bool permanent = false,
|
||||
required InstanceBuilderCallback<S> builder,
|
||||
bool fenix = false,
|
||||
}) {
|
||||
final key = _getKey(S, name);
|
||||
|
||||
if (_singl.containsKey(key)) {
|
||||
final dep = _singl[key];
|
||||
if (dep != null && dep.isDirty) {
|
||||
_singl[key] = _InstanceBuilderFactory<S>(
|
||||
isSingleton,
|
||||
builder,
|
||||
permanent,
|
||||
false,
|
||||
fenix,
|
||||
name,
|
||||
lateRemove: dep as _InstanceBuilderFactory<S>,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_singl[key] = _InstanceBuilderFactory<S>(
|
||||
isSingleton,
|
||||
builder,
|
||||
permanent,
|
||||
false,
|
||||
fenix,
|
||||
name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the dependencies for a Class Instance [S] (or tag),
|
||||
/// If its a Controller, it starts the lifecycle process.
|
||||
/// Optionally associating the current Route to the lifetime of the instance,
|
||||
/// if `Get.smartManagement` is marked as [SmartManagement.full] or
|
||||
/// [SmartManagement.keepFactory]
|
||||
/// Only flags `isInit` if it's using `Get.create()`
|
||||
/// (not for Singletons access).
|
||||
/// Returns the instance if not initialized, required for Get.create() to
|
||||
/// work properly.
|
||||
S? _initDependencies<S>({String? name}) {
|
||||
final key = _getKey(S, name);
|
||||
final isInit = _singl[key]!.isInit;
|
||||
S? i;
|
||||
if (!isInit) {
|
||||
i = _startController<S>(tag: name);
|
||||
if (_singl[key]!.isSingleton!) {
|
||||
_singl[key]!.isInit = true;
|
||||
if (Get.smartManagement != SmartManagement.onlyBuilder) {
|
||||
RouterReportManager.reportDependencyLinkedToRoute(_getKey(S, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
InstanceInfo getInstanceInfo<S>({String? tag}) {
|
||||
final build = _getDependency<S>(tag: tag);
|
||||
|
||||
return InstanceInfo(
|
||||
isPermanent: build?.permanent,
|
||||
isSingleton: build?.isSingleton,
|
||||
isRegistered: isRegistered<S>(tag: tag),
|
||||
isPrepared: !(build?.isInit ?? true),
|
||||
isInit: build?.isInit,
|
||||
);
|
||||
}
|
||||
|
||||
_InstanceBuilderFactory? _getDependency<S>({String? tag, String? key}) {
|
||||
final newKey = key ?? _getKey(S, tag);
|
||||
|
||||
if (!_singl.containsKey(newKey)) {
|
||||
Get.log('Instance "$newKey" is not registered.', isError: true);
|
||||
return null;
|
||||
} else {
|
||||
return _singl[newKey];
|
||||
}
|
||||
}
|
||||
|
||||
void markAsDirty<S>({String? tag, String? key}) {
|
||||
final newKey = key ?? _getKey(S, tag);
|
||||
if (_singl.containsKey(newKey)) {
|
||||
final dep = _singl[newKey];
|
||||
if (dep != null && !dep.permanent) {
|
||||
dep.isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the controller
|
||||
S _startController<S>({String? tag}) {
|
||||
final key = _getKey(S, tag);
|
||||
final i = _singl[key]!.getDependency() as S;
|
||||
if (i is GetLifeCycleBase) {
|
||||
i.onStart();
|
||||
if (tag == null) {
|
||||
Get.log('Instance "$S" has been initialized');
|
||||
} else {
|
||||
Get.log('Instance "$S" with tag "$tag" has been initialized');
|
||||
}
|
||||
if (!_singl[key]!.isSingleton!) {
|
||||
RouterReportManager.appendRouteByCreate(i);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
S putOrFind<S>(InstanceBuilderCallback<S> dep, {String? tag}) {
|
||||
final key = _getKey(S, tag);
|
||||
|
||||
if (_singl.containsKey(key)) {
|
||||
return _singl[key]!.getDependency() as S;
|
||||
} else {
|
||||
return GetInstance().put(dep(), tag: tag);
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the registered type <[S]> (or [tag])
|
||||
/// In case of using Get.[create] to register a type <[S]> or [tag],
|
||||
/// it will create an instance each time you call [find].
|
||||
/// If the registered type <[S]> (or [tag]) is a Controller,
|
||||
/// it will initialize it's lifecycle.
|
||||
S find<S>({String? tag}) {
|
||||
final key = _getKey(S, tag);
|
||||
if (isRegistered<S>(tag: tag)) {
|
||||
final dep = _singl[key];
|
||||
if (dep == null) {
|
||||
if (tag == null) {
|
||||
throw 'Class "$S" is not registered';
|
||||
} else {
|
||||
throw 'Class "$S" with tag "$tag" is not registered';
|
||||
}
|
||||
}
|
||||
|
||||
// if (dep.lateRemove != null) {
|
||||
// dep.isDirty = true;
|
||||
// if(dep.fenix)
|
||||
// }
|
||||
|
||||
/// although dirty solution, the lifecycle starts inside
|
||||
/// `initDependencies`, so we have to return the instance from there
|
||||
/// to make it compatible with `Get.create()`.
|
||||
final i = _initDependencies<S>(name: tag);
|
||||
return i ?? dep.getDependency() as S;
|
||||
} else {
|
||||
// ignore: lines_longer_than_80_chars
|
||||
throw '"$S" not found. You need to call "Get.put($S())" or "Get.lazyPut(()=>$S())"';
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the key based on [type] (and optionally a [name])
|
||||
/// to register an Instance Builder in the hashmap.
|
||||
String _getKey(Type type, String? name) {
|
||||
return name == null ? type.toString() : type.toString() + name;
|
||||
}
|
||||
|
||||
/// Clears all registered instances (and/or tags).
|
||||
/// Even the persistent ones.
|
||||
/// This should be used at the end or tearDown of unit tests.
|
||||
///
|
||||
/// `clearFactory` clears the callbacks registered by [lazyPut]
|
||||
/// `clearRouteBindings` clears Instances associated with routes.
|
||||
///
|
||||
bool resetInstance(
|
||||
{@deprecated bool clearFactory = true, bool clearRouteBindings = true}) {
|
||||
// if (clearFactory) _factory.clear();
|
||||
// deleteAll(force: true);
|
||||
if (clearRouteBindings) RouterReportManager.clearRouteKeys();
|
||||
_singl.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Delete registered Class Instance [S] (or [tag]) and, closes any open
|
||||
/// controllers `DisposableInterface`, cleans up the memory
|
||||
///
|
||||
/// /// Deletes the Instance<[S]>, cleaning the memory.
|
||||
// ///
|
||||
// /// - [tag] Optional "tag" used to register the Instance
|
||||
// /// - [key] For internal usage, is the processed key used to register
|
||||
// /// the Instance. **don't use** it unless you know what you are doing.
|
||||
|
||||
/// Deletes the Instance<[S]>, cleaning the memory and closes any open
|
||||
/// controllers (`DisposableInterface`).
|
||||
///
|
||||
/// - [tag] Optional "tag" used to register the Instance
|
||||
/// - [key] For internal usage, is the processed key used to register
|
||||
/// the Instance. **don't use** it unless you know what you are doing.
|
||||
/// - [force] Will delete an Instance even if marked as `permanent`.
|
||||
bool delete<S>({String? tag, String? key, bool force = false}) {
|
||||
final newKey = key ?? _getKey(S, tag);
|
||||
|
||||
if (!_singl.containsKey(newKey)) {
|
||||
Get.log('Instance "$newKey" already removed.', isError: true);
|
||||
return false;
|
||||
}
|
||||
|
||||
final dep = _singl[newKey];
|
||||
|
||||
if (dep == null) return false;
|
||||
|
||||
final _InstanceBuilderFactory builder;
|
||||
if (dep.isDirty) {
|
||||
builder = dep.lateRemove ?? dep;
|
||||
} else {
|
||||
builder = dep;
|
||||
}
|
||||
|
||||
if (builder.permanent && !force) {
|
||||
Get.log(
|
||||
// ignore: lines_longer_than_80_chars
|
||||
'"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.',
|
||||
isError: true,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
final i = builder.dependency;
|
||||
|
||||
if (i is GetxServiceMixin && !force) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i is GetLifeCycleBase) {
|
||||
i.onDelete();
|
||||
Get.log('"$newKey" onDelete() called');
|
||||
}
|
||||
|
||||
if (builder.fenix) {
|
||||
builder.dependency = null;
|
||||
builder.isInit = false;
|
||||
return true;
|
||||
} else {
|
||||
if (dep.lateRemove != null) {
|
||||
dep.lateRemove = null;
|
||||
Get.log('"$newKey" deleted from memory');
|
||||
return false;
|
||||
} else {
|
||||
_singl.remove(newKey);
|
||||
if (_singl.containsKey(newKey)) {
|
||||
Get.log('Error removing object "$newKey"', isError: true);
|
||||
} else {
|
||||
Get.log('"$newKey" deleted from memory');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete all registered Class Instances and, closes any open
|
||||
/// controllers `DisposableInterface`, cleans up the memory
|
||||
///
|
||||
/// - [force] Will delete the Instances even if marked as `permanent`.
|
||||
void deleteAll({bool force = false}) {
|
||||
final keys = _singl.keys.toList();
|
||||
for (final key in keys) {
|
||||
delete(key: key, force: force);
|
||||
}
|
||||
}
|
||||
|
||||
void reloadAll({bool force = false}) {
|
||||
_singl.forEach((key, value) {
|
||||
if (value.permanent && !force) {
|
||||
Get.log('Instance "$key" is permanent. Skipping reload');
|
||||
} else {
|
||||
value.dependency = null;
|
||||
value.isInit = false;
|
||||
Get.log('Instance "$key" was reloaded.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void reload<S>({
|
||||
String? tag,
|
||||
String? key,
|
||||
bool force = false,
|
||||
}) {
|
||||
final newKey = key ?? _getKey(S, tag);
|
||||
|
||||
final builder = _getDependency<S>(tag: tag, key: newKey);
|
||||
if (builder == null) return;
|
||||
|
||||
if (builder.permanent && !force) {
|
||||
Get.log(
|
||||
'''Instance "$newKey" is permanent. Use [force = true] to force the restart.''',
|
||||
isError: true,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final i = builder.dependency;
|
||||
|
||||
if (i is GetxServiceMixin && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i is GetLifeCycleBase) {
|
||||
i.onDelete();
|
||||
Get.log('"$newKey" onDelete() called');
|
||||
}
|
||||
|
||||
builder.dependency = null;
|
||||
builder.isInit = false;
|
||||
Get.log('Instance "$newKey" was restarted.');
|
||||
}
|
||||
|
||||
/// Check if a Class Instance<[S]> (or [tag]) is registered in memory.
|
||||
/// - [tag] is optional, if you used a [tag] to register the Instance.
|
||||
bool isRegistered<S>({String? tag}) => _singl.containsKey(_getKey(S, tag));
|
||||
|
||||
/// Checks if a lazy factory callback `Get.lazyPut()` that returns an
|
||||
/// Instance<[S]> is registered in memory.
|
||||
/// - [tag] is optional, if you used a [tag] to register the lazy Instance.
|
||||
bool isPrepared<S>({String? tag}) {
|
||||
final newKey = _getKey(S, tag);
|
||||
|
||||
final builder = _getDependency<S>(tag: tag, key: newKey);
|
||||
if (builder == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!builder.isInit) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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>()`.
|
||||
class _InstanceBuilderFactory<S> {
|
||||
/// Marks the Builder as a single instance.
|
||||
/// For reusing [dependency] instead of [builderFunc]
|
||||
bool? isSingleton;
|
||||
|
||||
/// When fenix mode is avaliable, when a new instance is need
|
||||
/// Instance manager will recreate a new instance of S
|
||||
bool fenix;
|
||||
|
||||
/// Stores the actual object instance when [isSingleton]=true.
|
||||
S? dependency;
|
||||
|
||||
/// Generates (and regenerates) the instance when [isSingleton]=false.
|
||||
/// Usually used by factory methods
|
||||
InstanceBuilderCallback<S> builderFunc;
|
||||
|
||||
/// Flag to persist the instance in memory,
|
||||
/// without considering `Get.smartManagement`
|
||||
bool permanent = false;
|
||||
|
||||
bool isInit = false;
|
||||
|
||||
_InstanceBuilderFactory<S>? lateRemove;
|
||||
|
||||
bool isDirty = false;
|
||||
|
||||
String? tag;
|
||||
|
||||
_InstanceBuilderFactory(
|
||||
this.isSingleton,
|
||||
this.builderFunc,
|
||||
this.permanent,
|
||||
this.isInit,
|
||||
this.fenix,
|
||||
this.tag, {
|
||||
this.lateRemove,
|
||||
});
|
||||
|
||||
void _showInitLog() {
|
||||
if (tag == null) {
|
||||
Get.log('Instance "$S" has been created');
|
||||
} else {
|
||||
Get.log('Instance "$S" has been created with tag "$tag"');
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the actual instance by it's [builderFunc] or the persisted instance.
|
||||
S getDependency() {
|
||||
if (isSingleton!) {
|
||||
if (dependency == null) {
|
||||
_showInitLog();
|
||||
dependency = builderFunc();
|
||||
}
|
||||
return dependency!;
|
||||
} else {
|
||||
return builderFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
104
packages/get/lib/get_instance/src/lifecycle.dart
Normal file
104
packages/get/lib/get_instance/src/lifecycle.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
import '../../get_core/get_core.dart';
|
||||
|
||||
/// Special callable class to keep the contract of a regular method, and avoid
|
||||
/// overrides if you extend the class that uses it, as Dart has no final
|
||||
/// methods.
|
||||
/// Used in `DisposableInterface` to avoid the danger of overriding onStart.
|
||||
class InternalFinalCallback<T> {
|
||||
ValueUpdater<T>? _callback;
|
||||
|
||||
InternalFinalCallback({ValueUpdater<T>? callback}) : _callback = callback;
|
||||
|
||||
T call() => _callback!.call();
|
||||
}
|
||||
|
||||
/// The [GetLifeCycle]
|
||||
///
|
||||
/// ```dart
|
||||
/// class SomeController with GetLifeCycle {
|
||||
/// SomeController() {
|
||||
/// configureLifeCycle();
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
mixin GetLifeCycleBase {
|
||||
/// 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>();
|
||||
|
||||
// /// The `configureLifeCycle` works as a constructor for the [GetLifeCycle]
|
||||
// ///
|
||||
// /// This method must be invoked in the constructor of the implementation
|
||||
// void configureLifeCycle() {
|
||||
// if (_initialized) return;
|
||||
// }
|
||||
|
||||
/// Internal callback that starts the cycle of this controller.
|
||||
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() {}
|
||||
|
||||
/// Called 1 frame after onInit(). It is the perfect place to enter
|
||||
/// navigation events, like snackbar, dialogs, or a new route, or
|
||||
/// async request.
|
||||
void 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.
|
||||
void onClose() {}
|
||||
|
||||
bool _initialized = false;
|
||||
|
||||
/// Checks whether the controller has already been initialized.
|
||||
bool get initialized => _initialized;
|
||||
|
||||
// Internal callback that starts the cycle of this controller.
|
||||
void _onStart() {
|
||||
if (_initialized) return;
|
||||
onInit();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
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 _onDelete() {
|
||||
if (_isClosed) return;
|
||||
_isClosed = true;
|
||||
onClose();
|
||||
}
|
||||
|
||||
void $configureLifeCycle() {
|
||||
_checkIfAlreadyConfigured();
|
||||
onStart._callback = _onStart;
|
||||
onDelete._callback = _onDelete;
|
||||
}
|
||||
|
||||
void _checkIfAlreadyConfigured() {
|
||||
if (_initialized) {
|
||||
throw """You can only call configureLifeCycle once.
|
||||
The proper place to insert it is in your class's constructor
|
||||
that inherits GetLifeCycle.""";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class GetLifeCycle with GetLifeCycleBase {
|
||||
GetLifeCycle() {
|
||||
$configureLifeCycle();
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow track difference between GetxServices and GetxControllers
|
||||
mixin GetxServiceMixin {}
|
||||
Reference in New Issue
Block a user