Jonny Borges
Committed by GitHub

Merge pull request #589 from roipeker/fix_get_create

Fix for Get.create() lifecycle
@@ -74,3 +74,9 @@ captures/ @@ -74,3 +74,9 @@ captures/
74 !.vscode/tasks.json 74 !.vscode/tasks.json
75 !.vscode/launch.json 75 !.vscode/launch.json
76 !.vscode/extensions.json 76 !.vscode/extensions.json
  77 +
  78 +example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig
  79 +
  80 +example/macos/Flutter/ephemeral/
  81 +
  82 +example/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -38,9 +38,15 @@ extension Inst on GetInterface { @@ -38,9 +38,15 @@ extension Inst on GetInterface {
38 {String tag, bool permanent = false}) async => 38 {String tag, bool permanent = false}) async =>
39 GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent); 39 GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
40 40
41 - /// Creates a new Instance<[S]> from the <[S]>[builder] callback. 41 + /// Creates a new Class Instance [S] from the builder callback[S].
42 /// Every time [find]<[S]>() is used, it calls the builder method to generate 42 /// Every time [find]<[S]>() is used, it calls the builder method to generate
43 /// a new Instance [S]. 43 /// a new Instance [S].
  44 + /// It also registers each [instance.onClose()] with the current
  45 + /// Route [GetConfig.currentRoute] to keep the lifecycle active.
  46 + /// Is important to know that the instances created are only stored per Route.
  47 + /// So, if you call `Get.delete<T>()` the "instance factory" used in this
  48 + /// method ([Get.create<T>()]) will be removed, but NOT the instances
  49 + /// already created by it.
44 /// 50 ///
45 /// Example: 51 /// Example:
46 /// 52 ///
  1 +import 'dart:async';
  2 +import 'dart:collection';
  3 +
1 import '../core/log.dart'; 4 import '../core/log.dart';
2 import '../navigation/root/smart_management.dart'; 5 import '../navigation/root/smart_management.dart';
3 import '../state_manager/rx/rx_core/rx_interface.dart'; 6 import '../state_manager/rx/rx_core/rx_interface.dart';
@@ -30,6 +33,12 @@ class GetInstance { @@ -30,6 +33,12 @@ class GetInstance {
30 /// created to manage the memory. 33 /// created to manage the memory.
31 static final Map<String, String> _routesKey = {}; 34 static final Map<String, String> _routesKey = {};
32 35
  36 + /// Stores the onClose() references of instances created with [Get.create()]
  37 + /// using the [GetConfig.currentRoute].
  38 + /// Experimental feature to keep the lifecycle and memory management with
  39 + /// non-singleton instances.
  40 + static final Map<String, HashSet<Function>> _routesByCreate = {};
  41 +
33 static final _queue = GetQueue(); 42 static final _queue = GetQueue();
34 43
35 /// Creates a new Instance<S> lazily from the [<S>builder()] callback. 44 /// Creates a new Instance<S> lazily from the [<S>builder()] callback.
@@ -101,6 +110,12 @@ class GetInstance { @@ -101,6 +110,12 @@ class GetInstance {
101 /// Creates a new Class Instance [S] from the builder callback[S]. 110 /// Creates a new Class Instance [S] from the builder callback[S].
102 /// Every time [find]<[S]>() is used, it calls the builder method to generate 111 /// Every time [find]<[S]>() is used, it calls the builder method to generate
103 /// a new Instance [S]. 112 /// a new Instance [S].
  113 + /// It also registers each [instance.onClose()] with the current
  114 + /// Route [GetConfig.currentRoute] to keep the lifecycle active.
  115 + /// Is important to know that the instances created are only stored per Route.
  116 + /// So, if you call `Get.delete<T>()` the "instance factory" used in this
  117 + /// method ([Get.create<T>()]) will be removed, but NOT the instances
  118 + /// already created by it.
104 /// 119 ///
105 /// Example: 120 /// Example:
106 /// 121 ///
@@ -144,6 +159,19 @@ class GetInstance { @@ -144,6 +159,19 @@ class GetInstance {
144 } 159 }
145 }); 160 });
146 161
  162 + /// Removes [Get.create()] instances registered in [routeName].
  163 + if (_routesByCreate.containsKey(routeName)) {
  164 + for (final onClose in _routesByCreate[routeName]) {
  165 + // assure the [DisposableInterface] instance holding a reference
  166 + // to [onClose()] wasn't disposed.
  167 + if (onClose != null) {
  168 + await onClose();
  169 + }
  170 + }
  171 + _routesByCreate[routeName].clear();
  172 + _routesByCreate.remove(routeName);
  173 + }
  174 +
147 for (final element in keysToRemove) { 175 for (final element in keysToRemove) {
148 await delete(key: element); 176 await delete(key: element);
149 } 177 }
@@ -159,14 +187,18 @@ class GetInstance { @@ -159,14 +187,18 @@ class GetInstance {
159 /// Optionally associating the current Route to the lifetime of the instance, 187 /// Optionally associating the current Route to the lifetime of the instance,
160 /// if [GetConfig.smartManagement] is marked as [SmartManagement.full] or 188 /// if [GetConfig.smartManagement] is marked as [SmartManagement.full] or
161 /// [GetConfig.keepFactory] 189 /// [GetConfig.keepFactory]
  190 + /// Only flags `isInit` if it's using `Get.create()`
  191 + /// (not for Singletons access).
162 bool _initDependencies<S>({String name}) { 192 bool _initDependencies<S>({String name}) {
163 final key = _getKey(S, name); 193 final key = _getKey(S, name);
164 final isInit = _singl[key].isInit; 194 final isInit = _singl[key].isInit;
165 if (!isInit) { 195 if (!isInit) {
166 _startController<S>(tag: name); 196 _startController<S>(tag: name);
167 - _singl[key].isInit = true;  
168 - if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {  
169 - _registerRouteInstance<S>(tag: name); 197 + if (_singl[key].isSingleton) {
  198 + _singl[key].isInit = true;
  199 + if (GetConfig.smartManagement != SmartManagement.onlyBuilder) {
  200 + _registerRouteInstance<S>(tag: name);
  201 + }
170 } 202 }
171 } 203 }
172 return true; 204 return true;
@@ -193,6 +225,10 @@ class GetInstance { @@ -193,6 +225,10 @@ class GetInstance {
193 i.onStart(); 225 i.onStart();
194 GetConfig.log('"$key" has been initialized'); 226 GetConfig.log('"$key" has been initialized');
195 } 227 }
  228 + if (!_singl[key].isSingleton && i.onClose != null) {
  229 + _routesByCreate[GetConfig.currentRoute] ??= HashSet<Function>();
  230 + _routesByCreate[GetConfig.currentRoute].add(i.onClose);
  231 + }
196 } 232 }
197 } 233 }
198 234