Line data Source code
1 : import 'package:get/src/root/smart_management.dart';
2 : import 'package:get/src/rx/rx_interface.dart';
3 : import 'package:get/src/typedefs/typedefs.dart';
4 :
5 : class GetConfig {
6 : //////////// INSTANCE MANAGER
7 24 : static Map<dynamic, dynamic> _singl = {};
8 21 : static Map<dynamic, FcBuilderFunc> _factory = {};
9 24 : static Map<String, String> routesKey = {};
10 16 : static SmartManagement smartManagement = SmartManagement.full;
11 : static bool isLogEnable = true;
12 : static String currentRoute;
13 : }
14 :
15 : class GetInstance {
16 8 : factory GetInstance() {
17 8 : if (_getInstance == null) _getInstance = GetInstance._();
18 : return _getInstance;
19 : }
20 8 : GetInstance._();
21 : static GetInstance _getInstance;
22 :
23 3 : void lazyPut<S>(FcBuilderFunc builder, {String tag}) {
24 3 : String key = _getKey(S, tag);
25 9 : GetConfig._factory.putIfAbsent(key, () => builder);
26 : }
27 :
28 1 : Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
29 : {String tag, bool permanent = false}) async {
30 3 : return put<S>(await builder(), tag: tag, permanent: permanent);
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 8 : GetConfig.routesKey
109 24 : .putIfAbsent(_getKey(S, tag), () => GetConfig.currentRoute);
110 : }
111 :
112 0 : S findByType<S>(Type type, {String tag}) {
113 0 : String key = _getKey(type, tag);
114 0 : return GetConfig._singl[key].getSependency() as S;
115 : }
116 :
117 8 : void initController<S>({String tag}) {
118 8 : String key = _getKey(S, tag);
119 24 : final i = GetConfig._singl[key].getSependency();
120 :
121 8 : if (i is DisposableInterface) {
122 7 : i.onStart();
123 14 : if (GetConfig.isLogEnable) print('[GET] $key has been initialized');
124 : }
125 : }
126 :
127 : /// Find a instance from required class
128 8 : S find<S>({String tag, FcBuilderFunc<S> instance}) {
129 8 : String key = _getKey(S, tag);
130 : bool callInit = false;
131 8 : if (isRegistred<S>(tag: tag)) {
132 8 : if (!isDependencyInit<S>() &&
133 16 : GetConfig.smartManagement != SmartManagement.onlyBuilder) {
134 8 : registerRouteInstance<S>(tag: tag);
135 : callInit = true;
136 : }
137 :
138 16 : FcBuilder builder = GetConfig._singl[key] as FcBuilder;
139 : if (builder == null) {
140 : if (tag == null) {
141 0 : throw "class ${S.toString()} is not register";
142 : } else {
143 0 : throw "class ${S.toString()} with tag '$tag' is not register";
144 : }
145 : }
146 : if (callInit) {
147 8 : initController<S>(tag: tag);
148 : }
149 :
150 24 : return GetConfig._singl[key].getSependency() as S;
151 : } else {
152 6 : if (!GetConfig._factory.containsKey(key))
153 0 : throw " $S not found. You need call put<$S>($S()) before";
154 :
155 : if (GetConfig.isLogEnable)
156 6 : print('[GET] $S instance was created at that time');
157 12 : S _value = put<S>(GetConfig._factory[key].call() as S);
158 :
159 3 : if (!isDependencyInit<S>() &&
160 0 : GetConfig.smartManagement != SmartManagement.onlyBuilder) {
161 0 : registerRouteInstance<S>(tag: tag);
162 : callInit = true;
163 : }
164 :
165 6 : if (GetConfig.smartManagement != SmartManagement.keepFactory) {
166 6 : GetConfig._factory.remove(key);
167 : }
168 :
169 : if (callInit) {
170 0 : initController<S>(tag: tag);
171 : }
172 : return _value;
173 : }
174 : }
175 :
176 : /// Remove dependency of [S] on dependency abstraction. For concrete class use delete
177 0 : void remove<S>({String tag}) {
178 0 : String key = _getKey(S, tag);
179 0 : FcBuilder builder = GetConfig._singl[key] as FcBuilder;
180 0 : final i = builder.dependency;
181 :
182 0 : if (i is DisposableInterface) {
183 0 : i.onClose();
184 0 : if (GetConfig.isLogEnable) print('[GET] onClose of $key called');
185 : }
186 0 : if (builder != null) builder.dependency = null;
187 0 : if (GetConfig._singl.containsKey(key)) {
188 0 : print('error on remove $key');
189 : } else {
190 0 : if (GetConfig.isLogEnable) print('[GET] $key removed from memory');
191 : }
192 : }
193 :
194 8 : String _getKey(Type type, String name) {
195 8 : return name == null ? type.toString() : type.toString() + name;
196 : }
197 :
198 1 : bool reset({bool clearFactory = true, bool clearRouteBindings = true}) {
199 2 : if (clearFactory) GetConfig._factory.clear();
200 2 : if (clearRouteBindings) GetConfig.routesKey.clear();
201 2 : GetConfig._singl.clear();
202 : return true;
203 : }
204 :
205 : /// Delete class instance on [S] and clean memory
206 6 : Future<bool> delete<S>({String tag, String key}) async {
207 : String newKey;
208 : if (key == null) {
209 6 : newKey = _getKey(S, tag);
210 : } else {
211 : newKey = key;
212 : }
213 :
214 12 : if (!GetConfig._singl.containsKey(newKey)) {
215 0 : print('Instance $newKey not found');
216 : return false;
217 : }
218 :
219 12 : FcBuilder builder = GetConfig._singl[newKey] as FcBuilder;
220 6 : if (builder.permanent) {
221 : (key == null)
222 0 : ? print(
223 0 : '[GET] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.')
224 0 : : print(
225 0 : '[GET] [$newKey] has been marked as permanent, SmartManagement is not authorized to delete it.');
226 : return false;
227 : }
228 6 : final i = builder.dependency;
229 :
230 6 : if (i is DisposableInterface) {
231 12 : await i.onClose();
232 12 : if (GetConfig.isLogEnable) print('[GET] onClose of $newKey called');
233 : }
234 :
235 24 : GetConfig._singl.removeWhere((oldkey, value) => (oldkey == newKey));
236 12 : if (GetConfig._singl.containsKey(newKey)) {
237 0 : print('[GET] error on remove object $newKey');
238 : } else {
239 12 : if (GetConfig.isLogEnable) print('[GET] $newKey deleted from memory');
240 : }
241 : // GetConfig.routesKey?.remove(key);
242 : return true;
243 : }
244 :
245 : /// check if instance is registred
246 8 : bool isRegistred<S>({String tag}) =>
247 24 : GetConfig._singl.containsKey(_getKey(S, tag));
248 :
249 : /// check if instance is prepared
250 6 : bool isPrepared<S>({String tag}) =>
251 18 : GetConfig._factory.containsKey(_getKey(S, tag));
252 : }
|