Line data Source code
1 : import 'root/smart_management.dart';
2 : import 'rx/rx_interface.dart';
3 : import 'typedefs/typedefs.dart';
4 :
5 :
6 : class GetConfig {
7 : //////////// INSTANCE MANAGER
8 24 : static Map<dynamic, dynamic> _singl = {};
9 21 : static Map<dynamic, FcBuilderFunc> _factory = {};
10 24 : static Map<String, String> routesKey = {};
11 16 : static SmartManagement smartManagement = SmartManagement.full;
12 : static bool isLogEnable = true;
13 : static String currentRoute;
14 : }
15 :
16 : class GetInstance {
17 8 : factory GetInstance() {
18 8 : if (_getInstance == null) _getInstance = GetInstance._();
19 : return _getInstance;
20 : }
21 8 : GetInstance._();
22 : static GetInstance _getInstance;
23 :
24 3 : void lazyPut<S>(FcBuilderFunc builder, {String tag}) {
25 3 : String key = _getKey(S, tag);
26 9 : GetConfig._factory.putIfAbsent(key, () => builder);
27 : }
28 :
29 1 : Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder, {String tag}) async {
30 3 : return put<S>(await builder(), tag: tag);
31 : }
32 :
33 : /// Inject class on Get Instance Manager
34 8 : S put<S>(
35 : S dependency, {
36 : String tag,
37 : bool permanent = false,
38 : bool overrideAbstract = false,
39 : FcBuilderFunc<S> builder,
40 : }) {
41 8 : _insert(
42 : isSingleton: true,
43 : replace: overrideAbstract,
44 : //?? (("$S" == "${dependency.runtimeType}") == false),
45 : name: tag,
46 : permanent: permanent,
47 8 : builder: builder ?? (() => dependency));
48 8 : return find<S>(tag: tag);
49 : }
50 :
51 : /// Create a new instance from builder class
52 : /// Example
53 : /// create(() => Repl());
54 : /// Repl a = find();
55 : /// Repl b = find();
56 : /// print(a==b); (false)
57 0 : void create<S>(
58 : FcBuilderFunc<S> builder, {
59 : String name,
60 : }) {
61 0 : _insert(isSingleton: false, name: name, builder: builder);
62 : }
63 :
64 8 : void _insert<S>({
65 : bool isSingleton,
66 : String name,
67 : bool replace = true,
68 : bool permanent = false,
69 : FcBuilderFunc<S> builder,
70 : }) {
71 0 : assert(builder != null);
72 8 : String key = _getKey(S, name);
73 : if (replace) {
74 0 : GetConfig._singl[key] = FcBuilder<S>(isSingleton, builder, permanent);
75 : } else {
76 16 : GetConfig._singl.putIfAbsent(
77 16 : key, () => FcBuilder<S>(isSingleton, builder, permanent));
78 : }
79 : }
80 :
81 3 : void removeDependencyByRoute(String routeName) async {
82 3 : List<String> keysToRemove = [];
83 9 : GetConfig.routesKey.forEach((key, value) {
84 : // if (value == routeName && value != null) {
85 3 : if (value == routeName) {
86 0 : keysToRemove.add(key);
87 : }
88 : });
89 3 : keysToRemove.forEach((element) async {
90 0 : await delete(key: element);
91 : });
92 3 : keysToRemove.forEach((element) {
93 0 : GetConfig.routesKey?.remove(element);
94 : });
95 3 : keysToRemove.clear();
96 : }
97 :
98 0 : bool isRouteDependecyNull<S>({String name}) {
99 0 : return (GetConfig.routesKey[_getKey(S, name)] == null);
100 : }
101 :
102 8 : bool isDependencyInit<S>({String name}) {
103 8 : String key = _getKey(S, name);
104 16 : return GetConfig.routesKey.containsKey(key);
105 : }
106 :
107 8 : void registerRouteInstance<S>({String tag}) {
108 : // print("Register route [$S] as ${currentRoute}");
109 8 : GetConfig.routesKey
110 24 : .putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute);
111 : }
112 :
113 0 : S findByType<S>(Type type, {String tag}) {
114 0 : String key = _getKey(type, tag);
115 0 : return GetConfig._singl[key].getSependency();
116 : }
117 :
118 8 : void initController<S>({String tag}) {
119 8 : String key = _getKey(S, tag);
120 24 : final i = GetConfig._singl[key].getSependency();
121 :
122 8 : if (i is DisposableInterface) {
123 7 : i.onStart();
124 14 : if (GetConfig.isLogEnable) print('[GETX] $key has been initialized');
125 : }
126 : }
127 :
128 : /// Find a instance from required class
129 8 : S find<S>({String tag, FcBuilderFunc<S> instance}) {
130 8 : String key = _getKey(S, tag);
131 : bool callInit = false;
132 8 : if (isRegistred<S>(tag: tag)) {
133 8 : if (!isDependencyInit<S>() &&
134 16 : GetConfig.smartManagement != SmartManagement.onlyBuilder) {
135 8 : registerRouteInstance<S>(tag: tag);
136 : callInit = true;
137 : }
138 :
139 16 : FcBuilder builder = GetConfig._singl[key];
140 : if (builder == null) {
141 : if (tag == null) {
142 0 : throw "class ${S.toString()} is not register";
143 : } else {
144 0 : throw "class ${S.toString()} with tag '$tag' is not register";
145 : }
146 : }
147 : if (callInit) {
148 8 : initController<S>(tag: tag);
149 : }
150 :
151 24 : return GetConfig._singl[key].getSependency();
152 : } else {
153 6 : if (!GetConfig._factory.containsKey(key))
154 0 : throw " $S not found. You need call put<$S>($S()) before";
155 :
156 : if (GetConfig.isLogEnable)
157 6 : print('[GETX] $S instance was created at that time');
158 12 : S _value = put<S>(GetConfig._factory[key].call() as S);
159 :
160 3 : if (!isDependencyInit<S>() &&
161 0 : GetConfig.smartManagement != SmartManagement.onlyBuilder) {
162 0 : registerRouteInstance<S>(tag: tag);
163 : callInit = true;
164 : }
165 :
166 6 : if (GetConfig.smartManagement != SmartManagement.keepFactory) {
167 6 : GetConfig._factory.remove(key);
168 : }
169 :
170 : if (callInit) {
171 0 : initController<S>(tag: tag);
172 : }
173 : return _value;
174 : }
175 : }
176 :
177 : /// Remove dependency of [S] on dependency abstraction. For concrete class use delete
178 0 : void remove<S>({String tag}) {
179 0 : String key = _getKey(S, tag);
180 0 : FcBuilder builder = GetConfig._singl[key];
181 0 : final i = builder.dependency;
182 :
183 0 : if (i is DisposableInterface) {
184 0 : i.onClose();
185 0 : if (GetConfig.isLogEnable) print('[GETX] onClose of $key called');
186 : }
187 0 : if (builder != null) builder.dependency = null;
188 0 : if (GetConfig._singl.containsKey(key)) {
189 0 : print('error on remove $key');
190 : } else {
191 0 : if (GetConfig.isLogEnable) print('[GETX] $key removed from memory');
192 : }
193 : }
194 :
195 8 : String _getKey(Type type, String name) {
196 8 : return name == null ? type.toString() : type.toString() + name;
197 : }
198 :
199 1 : bool reset({bool clearFactory = true, bool clearRouteBindings = true}) {
200 2 : if (clearFactory) GetConfig._factory.clear();
201 2 : if (clearRouteBindings) GetConfig.routesKey.clear();
202 2 : GetConfig._singl.clear();
203 : return true;
204 : }
205 :
206 : /// Delete class instance on [S] and clean memory
207 6 : Future<bool> delete<S>({String tag, String key}) async {
208 : String newKey;
209 : if (key == null) {
210 6 : newKey = _getKey(S, tag);
211 : } else {
212 : newKey = key;
213 : }
214 :
215 12 : if (!GetConfig._singl.containsKey(newKey)) {
216 0 : print('Instance $newKey not found');
217 : return false;
218 : }
219 :
220 12 : FcBuilder builder = GetConfig._singl[newKey];
221 6 : if (builder.permanent) {
222 : (key == null)
223 0 : ? print(
224 0 : '[GETX] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.')
225 0 : : print(
226 0 : '[GETX] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.');
227 : return false;
228 : }
229 6 : final i = builder.dependency;
230 :
231 6 : if (i is DisposableInterface) {
232 12 : await i.onClose();
233 12 : if (GetConfig.isLogEnable) print('[GETX] onClose of $newKey called');
234 : }
235 :
236 24 : GetConfig._singl.removeWhere((oldkey, value) => (oldkey == newKey));
237 12 : if (GetConfig._singl.containsKey(newKey)) {
238 0 : print('[GETX] error on remove object $newKey');
239 : } else {
240 12 : if (GetConfig.isLogEnable) print('[GETX] $newKey deleted from memory');
241 : }
242 : // GetConfig.routesKey?.remove(key);
243 : return true;
244 : }
245 :
246 : /// check if instance is registred
247 8 : bool isRegistred<S>({String tag}) =>
248 24 : GetConfig._singl.containsKey(_getKey(S, tag));
249 :
250 : /// check if instance is prepared
251 6 : bool isPrepared<S>({String tag}) =>
252 18 : GetConfig._factory.containsKey(_getKey(S, tag));
253 : }
|