refactor getview from scratch, reformulate rx variables, add error handler to wo…
…rkers, improve RxList, RxMap and RxSet factorys constructors, fix GetStream addError, refactor instance manager, add patch method to http
Showing
15 changed files
with
382 additions
and
191 deletions
1 | class Logger { | 1 | class Logger { |
2 | // Sample of abstract logging function | 2 | // Sample of abstract logging function |
3 | static void write(String text, {bool isError = false}) { | 3 | static void write(String text, {bool isError = false}) { |
4 | - print('** $text [$isError]'); | 4 | + Future.microtask(() => print('** $text. isError: [$isError]')); |
5 | } | 5 | } |
6 | } | 6 | } |
@@ -253,25 +253,6 @@ class GetHttpClient { | @@ -253,25 +253,6 @@ class GetHttpClient { | ||
253 | )); | 253 | )); |
254 | } | 254 | } |
255 | 255 | ||
256 | - Future<Request<T>> _post<T>( | ||
257 | - String url, { | ||
258 | - String contentType, | ||
259 | - @required dynamic body, | ||
260 | - Map<String, dynamic> query, | ||
261 | - Decoder<T> decoder, | ||
262 | - @required Progress uploadProgress, | ||
263 | - }) { | ||
264 | - return _requestWithBody<T>( | ||
265 | - url, | ||
266 | - contentType, | ||
267 | - body, | ||
268 | - 'post', | ||
269 | - query, | ||
270 | - decoder ?? (defaultDecoder as Decoder<T>), | ||
271 | - uploadProgress, | ||
272 | - ); | ||
273 | - } | ||
274 | - | ||
275 | Future<Request<T>> _request<T>( | 256 | Future<Request<T>> _request<T>( |
276 | String url, | 257 | String url, |
277 | String method, { | 258 | String method, { |
@@ -292,25 +273,6 @@ class GetHttpClient { | @@ -292,25 +273,6 @@ class GetHttpClient { | ||
292 | ); | 273 | ); |
293 | } | 274 | } |
294 | 275 | ||
295 | - Future<Request<T>> _put<T>( | ||
296 | - String url, { | ||
297 | - String contentType, | ||
298 | - @required dynamic body, | ||
299 | - @required Map<String, dynamic> query, | ||
300 | - Decoder<T> decoder, | ||
301 | - @required Progress uploadProgress, | ||
302 | - }) { | ||
303 | - return _requestWithBody<T>( | ||
304 | - url, | ||
305 | - contentType, | ||
306 | - body, | ||
307 | - 'put', | ||
308 | - query, | ||
309 | - decoder ?? (defaultDecoder as Decoder<T>), | ||
310 | - uploadProgress, | ||
311 | - ); | ||
312 | - } | ||
313 | - | ||
314 | Request<T> _delete<T>( | 276 | Request<T> _delete<T>( |
315 | String url, | 277 | String url, |
316 | String contentType, | 278 | String contentType, |
@@ -329,6 +291,40 @@ class GetHttpClient { | @@ -329,6 +291,40 @@ class GetHttpClient { | ||
329 | ); | 291 | ); |
330 | } | 292 | } |
331 | 293 | ||
294 | + Future<Response<T>> patch<T>( | ||
295 | + String url, { | ||
296 | + dynamic body, | ||
297 | + String contentType, | ||
298 | + Map<String, String> headers, | ||
299 | + Map<String, dynamic> query, | ||
300 | + Decoder<T> decoder, | ||
301 | + Progress uploadProgress, | ||
302 | + // List<MultipartFile> files, | ||
303 | + }) async { | ||
304 | + try { | ||
305 | + var response = await _performRequest<T>( | ||
306 | + () => _request<T>( | ||
307 | + url, | ||
308 | + 'patch', | ||
309 | + contentType: contentType, | ||
310 | + body: body, | ||
311 | + query: query, | ||
312 | + decoder: decoder, | ||
313 | + uploadProgress: uploadProgress, | ||
314 | + ), | ||
315 | + headers: headers, | ||
316 | + ); | ||
317 | + return response; | ||
318 | + } on Exception catch (e) { | ||
319 | + if (!errorSafety) { | ||
320 | + throw GetHttpException(e.toString()); | ||
321 | + } | ||
322 | + return Future.value(Response<T>( | ||
323 | + statusText: 'Can not connect to server. Reason: $e', | ||
324 | + )); | ||
325 | + } | ||
326 | + } | ||
327 | + | ||
332 | Future<Response<T>> post<T>( | 328 | Future<Response<T>> post<T>( |
333 | String url, { | 329 | String url, { |
334 | dynamic body, | 330 | dynamic body, |
@@ -341,8 +337,9 @@ class GetHttpClient { | @@ -341,8 +337,9 @@ class GetHttpClient { | ||
341 | }) async { | 337 | }) async { |
342 | try { | 338 | try { |
343 | var response = await _performRequest<T>( | 339 | var response = await _performRequest<T>( |
344 | - () => _post<T>( | 340 | + () => _request<T>( |
345 | url, | 341 | url, |
342 | + 'post', | ||
346 | contentType: contentType, | 343 | contentType: contentType, |
347 | body: body, | 344 | body: body, |
348 | query: query, | 345 | query: query, |
@@ -407,8 +404,9 @@ class GetHttpClient { | @@ -407,8 +404,9 @@ class GetHttpClient { | ||
407 | }) async { | 404 | }) async { |
408 | try { | 405 | try { |
409 | var response = await _performRequest<T>( | 406 | var response = await _performRequest<T>( |
410 | - () => _put<T>( | 407 | + () => _request<T>( |
411 | url, | 408 | url, |
409 | + 'put', | ||
412 | contentType: contentType, | 410 | contentType: contentType, |
413 | query: query, | 411 | query: query, |
414 | body: body, | 412 | body: body, |
1 | import 'dart:async'; | 1 | import 'dart:async'; |
2 | import 'dart:collection'; | 2 | import 'dart:collection'; |
3 | -import '../../get_core/get_core.dart'; | 3 | + |
4 | +import 'package:get/utils.dart'; | ||
4 | 5 | ||
5 | import 'lifecycle.dart'; | 6 | import 'lifecycle.dart'; |
6 | 7 | ||
@@ -19,7 +20,7 @@ class GetInstance { | @@ -19,7 +20,7 @@ class GetInstance { | ||
19 | 20 | ||
20 | /// Holds a reference to every registered callback when using | 21 | /// Holds a reference to every registered callback when using |
21 | /// [Get.lazyPut()] | 22 | /// [Get.lazyPut()] |
22 | - static final Map<String, _Lazy> _factory = {}; | 23 | + // static final Map<String, _Lazy> _factory = {}; |
23 | 24 | ||
24 | /// Holds a reference to [Get.reference] when the Instance was | 25 | /// Holds a reference to [Get.reference] when the Instance was |
25 | /// created to manage the memory. | 26 | /// created to manage the memory. |
@@ -56,10 +57,14 @@ class GetInstance { | @@ -56,10 +57,14 @@ class GetInstance { | ||
56 | void lazyPut<S>( | 57 | void lazyPut<S>( |
57 | InstanceBuilderCallback<S> builder, { | 58 | InstanceBuilderCallback<S> builder, { |
58 | String tag, | 59 | String tag, |
59 | - bool fenix = false, | 60 | + bool fenix, |
60 | }) { | 61 | }) { |
61 | - final key = _getKey(S, tag); | ||
62 | - _factory.putIfAbsent(key, () => _Lazy(builder, fenix)); | 62 | + _insert( |
63 | + isSingleton: true, | ||
64 | + name: tag, | ||
65 | + permanent: fenix ?? Get.smartManagement == SmartManagement.keepFactory, | ||
66 | + builder: builder, | ||
67 | + ); | ||
63 | } | 68 | } |
64 | 69 | ||
65 | void injector<S>( | 70 | void injector<S>( |
@@ -133,7 +138,11 @@ class GetInstance { | @@ -133,7 +138,11 @@ class GetInstance { | ||
133 | bool permanent = true, | 138 | bool permanent = true, |
134 | }) { | 139 | }) { |
135 | _insert( | 140 | _insert( |
136 | - isSingleton: false, name: tag, builder: builder, permanent: permanent); | 141 | + isSingleton: false, |
142 | + name: tag, | ||
143 | + builder: builder, | ||
144 | + permanent: permanent, | ||
145 | + ); | ||
137 | } | 146 | } |
138 | 147 | ||
139 | /// Injects the Instance [S] builder into the [_singleton] HashMap. | 148 | /// Injects the Instance [S] builder into the [_singleton] HashMap. |
@@ -240,17 +249,6 @@ class GetInstance { | @@ -240,17 +249,6 @@ class GetInstance { | ||
240 | if (_singl.containsKey(key)) { | 249 | if (_singl.containsKey(key)) { |
241 | return _singl[key].getDependency() as S; | 250 | return _singl[key].getDependency() as S; |
242 | } else { | 251 | } else { |
243 | - if (_factory.containsKey(key)) { | ||
244 | - final _value = put<S>((_factory[key].builder() as S), tag: tag); | ||
245 | - | ||
246 | - if (Get.smartManagement != SmartManagement.keepFactory) { | ||
247 | - if (!_factory[key].fenix) { | ||
248 | - _factory.remove(key); | ||
249 | - } | ||
250 | - } | ||
251 | - return _value; | ||
252 | - } | ||
253 | - | ||
254 | return GetInstance().put(dep(), tag: tag); | 252 | return GetInstance().put(dep(), tag: tag); |
255 | } | 253 | } |
256 | } | 254 | } |
@@ -277,22 +275,9 @@ class GetInstance { | @@ -277,22 +275,9 @@ class GetInstance { | ||
277 | final i = _initDependencies<S>(name: tag); | 275 | final i = _initDependencies<S>(name: tag); |
278 | return i ?? _singl[key].getDependency() as S; | 276 | return i ?? _singl[key].getDependency() as S; |
279 | } else { | 277 | } else { |
280 | - if (!_factory.containsKey(key)) { | ||
281 | // ignore: lines_longer_than_80_chars | 278 | // ignore: lines_longer_than_80_chars |
282 | throw '"$S" not found. You need to call "Get.put($S())" or "Get.lazyPut(()=>$S())"'; | 279 | throw '"$S" not found. You need to call "Get.put($S())" or "Get.lazyPut(()=>$S())"'; |
283 | } | 280 | } |
284 | - | ||
285 | - Get.log('Lazy instance "$S" created'); | ||
286 | - final _value = put<S>(_factory[key].builder() as S, tag: tag); | ||
287 | - _initDependencies<S>(name: tag); | ||
288 | - | ||
289 | - if (Get.smartManagement != SmartManagement.keepFactory && | ||
290 | - !_factory[key].fenix) { | ||
291 | - _factory.remove(key); | ||
292 | - } | ||
293 | - | ||
294 | - return _value; | ||
295 | - } | ||
296 | } | 281 | } |
297 | 282 | ||
298 | /// Generates the key based on [type] (and optionally a [name]) | 283 | /// Generates the key based on [type] (and optionally a [name]) |
@@ -308,7 +293,7 @@ class GetInstance { | @@ -308,7 +293,7 @@ class GetInstance { | ||
308 | /// [clearRouteBindings] clears Instances associated with routes. | 293 | /// [clearRouteBindings] clears Instances associated with routes. |
309 | /// | 294 | /// |
310 | bool reset({bool clearFactory = true, bool clearRouteBindings = true}) { | 295 | bool reset({bool clearFactory = true, bool clearRouteBindings = true}) { |
311 | - if (clearFactory) _factory.clear(); | 296 | + // if (clearFactory) _factory.clear(); |
312 | if (clearRouteBindings) _routesKey.clear(); | 297 | if (clearRouteBindings) _routesKey.clear(); |
313 | _singl.clear(); | 298 | _singl.clear(); |
314 | return true; | 299 | return true; |
@@ -330,13 +315,13 @@ class GetInstance { | @@ -330,13 +315,13 @@ class GetInstance { | ||
330 | /// - [key] For internal usage, is the processed key used to register | 315 | /// - [key] For internal usage, is the processed key used to register |
331 | /// the Instance. **don't use** it unless you know what you are doing. | 316 | /// the Instance. **don't use** it unless you know what you are doing. |
332 | /// - [force] Will delete an Instance even if marked as [permanent]. | 317 | /// - [force] Will delete an Instance even if marked as [permanent]. |
333 | - bool delete<S>({String tag, String key, bool force = false}) { | 318 | + Future<bool> delete<S>({String tag, String key, bool force = false}) { |
334 | // return _queue.secure<bool>(() { | 319 | // return _queue.secure<bool>(() { |
335 | return _delete<S>(tag: tag, key: key, force: force); | 320 | return _delete<S>(tag: tag, key: key, force: force); |
336 | // }); | 321 | // }); |
337 | } | 322 | } |
338 | 323 | ||
339 | - bool _delete<S>({String tag, String key, bool force = false}) { | 324 | + Future<bool> _delete<S>({String tag, String key, bool force = false}) async { |
340 | final newKey = key ?? _getKey(S, tag); | 325 | final newKey = key ?? _getKey(S, tag); |
341 | 326 | ||
342 | if (!_singl.containsKey(newKey)) { | 327 | if (!_singl.containsKey(newKey)) { |
@@ -358,18 +343,20 @@ class GetInstance { | @@ -358,18 +343,20 @@ class GetInstance { | ||
358 | if (i is GetxServiceMixin && !force) { | 343 | if (i is GetxServiceMixin && !force) { |
359 | return false; | 344 | return false; |
360 | } | 345 | } |
346 | + await Get.asap(() { | ||
361 | if (i is GetLifeCycle) { | 347 | if (i is GetLifeCycle) { |
362 | i.onDelete(); | 348 | i.onDelete(); |
363 | Get.log('"$newKey" onClose() called'); | 349 | Get.log('"$newKey" onClose() called'); |
364 | } | 350 | } |
365 | 351 | ||
366 | - _singl.removeWhere((oldKey, value) => (oldKey == newKey)); | 352 | + _singl.remove(newKey); |
353 | + | ||
367 | if (_singl.containsKey(newKey)) { | 354 | if (_singl.containsKey(newKey)) { |
368 | Get.log('Error removing object "$newKey"', isError: true); | 355 | Get.log('Error removing object "$newKey"', isError: true); |
369 | } else { | 356 | } else { |
370 | Get.log('"$newKey" deleted from memory'); | 357 | Get.log('"$newKey" deleted from memory'); |
371 | } | 358 | } |
372 | - // _routesKey?.remove(key); | 359 | + }); |
373 | return true; | 360 | return true; |
374 | } | 361 | } |
375 | 362 | ||
@@ -380,7 +367,20 @@ class GetInstance { | @@ -380,7 +367,20 @@ class GetInstance { | ||
380 | /// Checks if a lazy factory callback ([Get.lazyPut()] that returns an | 367 | /// Checks if a lazy factory callback ([Get.lazyPut()] that returns an |
381 | /// Instance<[S]> is registered in memory. | 368 | /// Instance<[S]> is registered in memory. |
382 | /// - [tag] is optional, if you used a [tag] to register the lazy Instance. | 369 | /// - [tag] is optional, if you used a [tag] to register the lazy Instance. |
383 | - bool isPrepared<S>({String tag}) => _factory.containsKey(_getKey(S, tag)); | 370 | + bool isPrepared<S>({String tag}) { |
371 | + final newKey = _getKey(S, tag); | ||
372 | + | ||
373 | + if (!_singl.containsKey(newKey)) { | ||
374 | + Get.log('Instance "$newKey" not found.', isError: true); | ||
375 | + return false; | ||
376 | + } | ||
377 | + | ||
378 | + final builder = _singl[newKey]; | ||
379 | + if (!builder.isInit) { | ||
380 | + return true; | ||
381 | + } | ||
382 | + return false; | ||
383 | + } | ||
384 | } | 384 | } |
385 | 385 | ||
386 | typedef InstanceBuilderCallback<S> = S Function(); | 386 | typedef InstanceBuilderCallback<S> = S Function(); |
@@ -420,13 +420,3 @@ class _InstanceBuilderFactory<S> { | @@ -420,13 +420,3 @@ class _InstanceBuilderFactory<S> { | ||
420 | return isSingleton ? dependency ??= builderFunc() : builderFunc(); | 420 | return isSingleton ? dependency ??= builderFunc() : builderFunc(); |
421 | } | 421 | } |
422 | } | 422 | } |
423 | - | ||
424 | -/// Internal class to register a future instance with [lazyPut], | ||
425 | -/// keeps a reference to the callback to be called. | ||
426 | -class _Lazy { | ||
427 | - bool fenix; | ||
428 | - bool permanent = false; | ||
429 | - InstanceBuilderCallback builder; | ||
430 | - | ||
431 | - _Lazy(this.builder, this.fenix); | ||
432 | -} |
@@ -384,14 +384,14 @@ class GetPageRoute<T> extends PageRoute<T> { | @@ -384,14 +384,14 @@ class GetPageRoute<T> extends PageRoute<T> { | ||
384 | 384 | ||
385 | @override | 385 | @override |
386 | void dispose() { | 386 | void dispose() { |
387 | - super.dispose(); | ||
388 | // if (Get.smartManagement != SmartManagement.onlyBuilder) { | 387 | // if (Get.smartManagement != SmartManagement.onlyBuilder) { |
389 | // WidgetsBinding.instance.addPostFrameCallback((_) => GetInstance() | 388 | // WidgetsBinding.instance.addPostFrameCallback((_) => GetInstance() |
390 | // .removeDependencyByRoute("${settings?.name ?? routeName}")); | 389 | // .removeDependencyByRoute("${settings?.name ?? routeName}")); |
391 | // } | 390 | // } |
391 | + | ||
392 | + super.dispose(); | ||
392 | if (Get.smartManagement != SmartManagement.onlyBuilder) { | 393 | if (Get.smartManagement != SmartManagement.onlyBuilder) { |
393 | - WidgetsBinding.instance.addPostFrameCallback( | ||
394 | - (_) => GetInstance().removeDependencyByRoute("$reference")); | 394 | + GetInstance().removeDependencyByRoute("$reference"); |
395 | } | 395 | } |
396 | 396 | ||
397 | final middlewareRunner = MiddlewareRunner(middlewares); | 397 | final middlewareRunner = MiddlewareRunner(middlewares); |
@@ -56,7 +56,12 @@ class GetStream<T> { | @@ -56,7 +56,12 @@ class GetStream<T> { | ||
56 | var itemsToRemove = <LightSubscription<T>>[]; | 56 | var itemsToRemove = <LightSubscription<T>>[]; |
57 | for (final item in _onData) { | 57 | for (final item in _onData) { |
58 | if (!item.isPaused) { | 58 | if (!item.isPaused) { |
59 | + if (stackTrace != null) { | ||
59 | item._onError?.call(error, stackTrace); | 60 | item._onError?.call(error, stackTrace); |
61 | + } else { | ||
62 | + item._onError?.call(error); | ||
63 | + } | ||
64 | + | ||
60 | if (item.cancelOnError) { | 65 | if (item.cancelOnError) { |
61 | //item.cancel?.call(); | 66 | //item.cancel?.call(); |
62 | itemsToRemove.add(item); | 67 | itemsToRemove.add(item); |
@@ -147,7 +152,7 @@ class LightSubscription<T> extends StreamSubscription<T> { | @@ -147,7 +152,7 @@ class LightSubscription<T> extends StreamSubscription<T> { | ||
147 | 152 | ||
148 | OnData<T> _data; | 153 | OnData<T> _data; |
149 | 154 | ||
150 | - dynamic _onError; | 155 | + Function _onError; |
151 | 156 | ||
152 | Callback _onDone; | 157 | Callback _onDone; |
153 | 158 |
@@ -166,6 +166,10 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | @@ -166,6 +166,10 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | ||
166 | _value = initial; | 166 | _value = initial; |
167 | } | 167 | } |
168 | 168 | ||
169 | + void addError(Object error, [StackTrace stackTrace]) { | ||
170 | + subject.addError(error, stackTrace); | ||
171 | + } | ||
172 | + | ||
169 | Stream<R> map<R>(R mapper(T data)) => stream.map(mapper); | 173 | Stream<R> map<R>(R mapper(T data)) => stream.map(mapper); |
170 | 174 | ||
171 | /// Uses a callback to update [value] internally, similar to [refresh], | 175 | /// Uses a callback to update [value] internally, similar to [refresh], |
@@ -198,6 +202,10 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | @@ -198,6 +202,10 @@ abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | ||
198 | class RxBool extends _RxImpl<bool> { | 202 | class RxBool extends _RxImpl<bool> { |
199 | RxBool([bool initial]) : super(initial); | 203 | RxBool([bool initial]) : super(initial); |
200 | 204 | ||
205 | + bool get isTrue => value; | ||
206 | + | ||
207 | + bool get isfalse => !isTrue; | ||
208 | + | ||
201 | bool operator &(bool other) => other && value; | 209 | bool operator &(bool other) => other && value; |
202 | 210 | ||
203 | bool operator |(bool other) => other || value; | 211 | bool operator |(bool other) => other || value; |
@@ -221,10 +229,134 @@ class RxBool extends _RxImpl<bool> { | @@ -221,10 +229,134 @@ class RxBool extends _RxImpl<bool> { | ||
221 | } | 229 | } |
222 | 230 | ||
223 | /// Rx class for `String` Type. | 231 | /// Rx class for `String` Type. |
224 | -class RxString extends _RxImpl<String> { | 232 | +class RxString extends _RxImpl<String> implements Comparable<String>, Pattern { |
225 | RxString([String initial]) : super(initial); | 233 | RxString([String initial]) : super(initial); |
226 | 234 | ||
227 | String operator +(String val) => _value + val; | 235 | String operator +(String val) => _value + val; |
236 | + | ||
237 | + /// Compares this string to [other]. | ||
238 | + @override | ||
239 | + int compareTo(String other) { | ||
240 | + return value.compareTo(other); | ||
241 | + } | ||
242 | + | ||
243 | + /// Returns true if this string ends with [other]. For example: | ||
244 | + /// | ||
245 | + /// 'Dart'.endsWith('t'); // true | ||
246 | + bool endsWith(String other) { | ||
247 | + return value.endsWith(other); | ||
248 | + } | ||
249 | + | ||
250 | + /// Returns true if this string starts with a match of [pattern]. | ||
251 | + bool startsWith(Pattern pattern, [int index = 0]) { | ||
252 | + return value.startsWith(pattern, index); | ||
253 | + } | ||
254 | + | ||
255 | + /// Returns the position of the first match of [pattern] in this string | ||
256 | + int indexOf(Pattern pattern, [int start = 0]) { | ||
257 | + return value.indexOf(pattern, start); | ||
258 | + } | ||
259 | + | ||
260 | + /// Returns the starting position of the last match [pattern] in this string, | ||
261 | + /// searching backward starting at [start], inclusive: | ||
262 | + int lastIndexOf(Pattern pattern, [int start]) { | ||
263 | + return value.lastIndexOf(pattern, start); | ||
264 | + } | ||
265 | + | ||
266 | + /// Returns true if this string is empty. | ||
267 | + bool get isEmpty => value.isEmpty; | ||
268 | + | ||
269 | + /// Returns true if this string is not empty. | ||
270 | + bool get isNotEmpty => !isEmpty; | ||
271 | + | ||
272 | + /// Returns the substring of this string that extends from [startIndex], | ||
273 | + /// inclusive, to [endIndex], exclusive | ||
274 | + String substring(int startIndex, [int endIndex]) { | ||
275 | + return value.substring(startIndex, endIndex); | ||
276 | + } | ||
277 | + | ||
278 | + /// Returns the string without any leading and trailing whitespace. | ||
279 | + String trim() { | ||
280 | + return value.trim(); | ||
281 | + } | ||
282 | + | ||
283 | + /// Returns the string without any leading whitespace. | ||
284 | + /// | ||
285 | + /// As [trim], but only removes leading whitespace. | ||
286 | + String trimLeft() { | ||
287 | + return value.trimLeft(); | ||
288 | + } | ||
289 | + | ||
290 | + /// Returns the string without any trailing whitespace. | ||
291 | + /// | ||
292 | + /// As [trim], but only removes trailing whitespace. | ||
293 | + String trimRight() { | ||
294 | + return value.trimRight(); | ||
295 | + } | ||
296 | + | ||
297 | + /// Pads this string on the left if it is shorter than [width]. | ||
298 | + /// | ||
299 | + /// Return a new string that prepends [padding] onto this string | ||
300 | + /// one time for each position the length is less than [width]. | ||
301 | + String padLeft(int width, [String padding = ' ']) { | ||
302 | + return value.padLeft(width, padding); | ||
303 | + } | ||
304 | + | ||
305 | + /// Pads this string on the right if it is shorter than [width]. | ||
306 | + | ||
307 | + /// Return a new string that appends [padding] after this string | ||
308 | + /// one time for each position the length is less than [width]. | ||
309 | + String padRight(int width, [String padding = ' ']) { | ||
310 | + return value.padRight(width, padding); | ||
311 | + } | ||
312 | + | ||
313 | + /// Returns true if this string contains a match of [other]: | ||
314 | + bool contains(Pattern other, [int startIndex = 0]) { | ||
315 | + return value.contains(other, startIndex); | ||
316 | + } | ||
317 | + | ||
318 | + /// Replaces all substrings that match [from] with [replace]. | ||
319 | + String replaceAll(Pattern from, String replace) { | ||
320 | + return value.replaceAll(from, replace); | ||
321 | + } | ||
322 | + | ||
323 | + /// Splits the string at matches of [pattern] and returns a list | ||
324 | + /// of substrings. | ||
325 | + List<String> split(Pattern pattern) { | ||
326 | + return value.split(pattern); | ||
327 | + } | ||
328 | + | ||
329 | + /// Returns an unmodifiable list of the UTF-16 code units of this string. | ||
330 | + List<int> get codeUnits => value.codeUnits; | ||
331 | + | ||
332 | + /// Returns an [Iterable] of Unicode code-points of this string. | ||
333 | + /// | ||
334 | + /// If the string contains surrogate pairs, they are combined and returned | ||
335 | + /// as one integer by this iterator. Unmatched surrogate halves are treated | ||
336 | + /// like valid 16-bit code-units. | ||
337 | + Runes get runes => value.runes; | ||
338 | + | ||
339 | + /// Converts all characters in this string to lower case. | ||
340 | + /// If the string is already in all lower case, this method returns `this`. | ||
341 | + String toLowerCase() { | ||
342 | + return value.toLowerCase(); | ||
343 | + } | ||
344 | + | ||
345 | + /// Converts all characters in this string to upper case. | ||
346 | + /// If the string is already in all upper case, this method returns `this`. | ||
347 | + String toUpperCase() { | ||
348 | + return value.toUpperCase(); | ||
349 | + } | ||
350 | + | ||
351 | + @override | ||
352 | + Iterable<Match> allMatches(String string, [int start = 0]) { | ||
353 | + return value.allMatches(string, start); | ||
354 | + } | ||
355 | + | ||
356 | + @override | ||
357 | + Match matchAsPrefix(String string, [int start = 0]) { | ||
358 | + return value.matchAsPrefix(string, start); | ||
359 | + } | ||
228 | } | 360 | } |
229 | 361 | ||
230 | /// Foundation class used for custom `Types` outside the common native Dart | 362 | /// Foundation class used for custom `Types` outside the common native Dart |
@@ -10,6 +10,35 @@ class RxList<E> extends ListMixin<E> | @@ -10,6 +10,35 @@ class RxList<E> extends ListMixin<E> | ||
10 | } | 10 | } |
11 | } | 11 | } |
12 | 12 | ||
13 | + factory RxList.filled(int length, E fill, {bool growable = false}) { | ||
14 | + return RxList(List.filled(length, fill, growable: growable)); | ||
15 | + } | ||
16 | + | ||
17 | + factory RxList.empty({bool growable = false}) { | ||
18 | + return RxList(List.empty(growable: growable)); | ||
19 | + } | ||
20 | + | ||
21 | + /// Creates a list containing all [elements]. | ||
22 | + factory RxList.from(Iterable elements, {bool growable = true}) { | ||
23 | + return RxList(List.from(elements, growable: growable)); | ||
24 | + } | ||
25 | + | ||
26 | + /// Creates a list from [elements]. | ||
27 | + factory RxList.of(Iterable<E> elements, {bool growable = true}) { | ||
28 | + return RxList(List.of(elements, growable: growable)); | ||
29 | + } | ||
30 | + | ||
31 | + /// Generates a list of values. | ||
32 | + factory RxList.generate(int length, E generator(int index), | ||
33 | + {bool growable = true}) { | ||
34 | + return RxList(List.generate(length, generator, growable: growable)); | ||
35 | + } | ||
36 | + | ||
37 | + /// Creates an unmodifiable list containing all [elements]. | ||
38 | + factory RxList.unmodifiable(Iterable elements) { | ||
39 | + return RxList(List.unmodifiable(elements)); | ||
40 | + } | ||
41 | + | ||
13 | @override | 42 | @override |
14 | Iterator<E> get iterator => value.iterator; | 43 | Iterator<E> get iterator => value.iterator; |
15 | 44 | ||
@@ -136,10 +165,6 @@ class RxList<E> extends ListMixin<E> | @@ -136,10 +165,6 @@ class RxList<E> extends ListMixin<E> | ||
136 | 165 | ||
137 | extension ListExtension<E> on List<E> { | 166 | extension ListExtension<E> on List<E> { |
138 | RxList<E> get obs { | 167 | RxList<E> get obs { |
139 | - if (this != null) { | ||
140 | return RxList<E>(this); | 168 | return RxList<E>(this); |
141 | - } else { | ||
142 | - return RxList<E>(null); | ||
143 | - } | ||
144 | } | 169 | } |
145 | } | 170 | } |
@@ -9,6 +9,25 @@ class RxMap<K, V> extends MapMixin<K, V> | @@ -9,6 +9,25 @@ class RxMap<K, V> extends MapMixin<K, V> | ||
9 | } | 9 | } |
10 | } | 10 | } |
11 | 11 | ||
12 | + factory RxMap.from(Map<K, V> other) { | ||
13 | + return RxMap(Map.from(other)); | ||
14 | + } | ||
15 | + | ||
16 | + /// Creates a [LinkedHashMap] with the same keys and values as [other]. | ||
17 | + factory RxMap.of(Map<K, V> other) { | ||
18 | + return RxMap(Map.of(other)); | ||
19 | + } | ||
20 | + | ||
21 | + ///Creates an unmodifiable hash based map containing the entries of [other]. | ||
22 | + factory RxMap.unmodifiable(Map<dynamic, dynamic> other) { | ||
23 | + return RxMap(Map.unmodifiable(other)); | ||
24 | + } | ||
25 | + | ||
26 | + /// Creates an identity map with the default implementation, [LinkedHashMap]. | ||
27 | + factory RxMap.identity() { | ||
28 | + return RxMap(Map.identity()); | ||
29 | + } | ||
30 | + | ||
12 | @override | 31 | @override |
13 | V operator [](Object key) { | 32 | V operator [](Object key) { |
14 | return value[key]; | 33 | return value[key]; |
@@ -43,11 +43,22 @@ typedef WorkerCallback<T> = Function(T callback); | @@ -43,11 +43,22 @@ typedef WorkerCallback<T> = Function(T callback); | ||
43 | /// void increment() => count + 1; | 43 | /// void increment() => count + 1; |
44 | /// } | 44 | /// } |
45 | /// ``` | 45 | /// ``` |
46 | -Worker ever<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
47 | - {dynamic condition = true}) { | ||
48 | - StreamSubscription sub = listener.listen((event) { | 46 | +Worker ever<T>( |
47 | + RxInterface<T> listener, | ||
48 | + WorkerCallback<T> callback, { | ||
49 | + dynamic condition = true, | ||
50 | + Function onError, | ||
51 | + void Function() onDone, | ||
52 | + bool cancelOnError, | ||
53 | +}) { | ||
54 | + StreamSubscription sub = listener.listen( | ||
55 | + (event) { | ||
49 | if (_conditional(condition)) callback(event); | 56 | if (_conditional(condition)) callback(event); |
50 | - }); | 57 | + }, |
58 | + onError: onError, | ||
59 | + onDone: onDone, | ||
60 | + cancelOnError: cancelOnError, | ||
61 | + ); | ||
51 | return Worker(sub.cancel, '[ever]'); | 62 | return Worker(sub.cancel, '[ever]'); |
52 | } | 63 | } |
53 | 64 | ||
@@ -55,13 +66,24 @@ Worker ever<T>(RxInterface<T> listener, WorkerCallback<T> callback, | @@ -55,13 +66,24 @@ Worker ever<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
55 | /// for the [callback] is common to all [listeners], | 66 | /// for the [callback] is common to all [listeners], |
56 | /// and the [callback] is executed to each one of them. The [Worker] is | 67 | /// and the [callback] is executed to each one of them. The [Worker] is |
57 | /// common to all, so [worker.dispose()] will cancel all streams. | 68 | /// common to all, so [worker.dispose()] will cancel all streams. |
58 | -Worker everAll(List<RxInterface> listeners, WorkerCallback callback, | ||
59 | - {dynamic condition = true}) { | 69 | +Worker everAll( |
70 | + List<RxInterface> listeners, | ||
71 | + WorkerCallback callback, { | ||
72 | + dynamic condition = true, | ||
73 | + Function onError, | ||
74 | + void Function() onDone, | ||
75 | + bool cancelOnError, | ||
76 | +}) { | ||
60 | final evers = <StreamSubscription>[]; | 77 | final evers = <StreamSubscription>[]; |
61 | for (var i in listeners) { | 78 | for (var i in listeners) { |
62 | - final sub = i.listen((event) { | 79 | + final sub = i.listen( |
80 | + (event) { | ||
63 | if (_conditional(condition)) callback(event); | 81 | if (_conditional(condition)) callback(event); |
64 | - }); | 82 | + }, |
83 | + onError: onError, | ||
84 | + onDone: onDone, | ||
85 | + cancelOnError: cancelOnError, | ||
86 | + ); | ||
65 | evers.add(sub); | 87 | evers.add(sub); |
66 | } | 88 | } |
67 | 89 | ||
@@ -96,17 +118,28 @@ Worker everAll(List<RxInterface> listeners, WorkerCallback callback, | @@ -96,17 +118,28 @@ Worker everAll(List<RxInterface> listeners, WorkerCallback callback, | ||
96 | /// void increment() => count + 1; | 118 | /// void increment() => count + 1; |
97 | /// } | 119 | /// } |
98 | ///``` | 120 | ///``` |
99 | -Worker once<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
100 | - {dynamic condition}) { | 121 | +Worker once<T>( |
122 | + RxInterface<T> listener, | ||
123 | + WorkerCallback<T> callback, { | ||
124 | + dynamic condition = true, | ||
125 | + Function onError, | ||
126 | + void Function() onDone, | ||
127 | + bool cancelOnError, | ||
128 | +}) { | ||
101 | Worker ref; | 129 | Worker ref; |
102 | StreamSubscription sub; | 130 | StreamSubscription sub; |
103 | - sub = listener.listen((event) { | 131 | + sub = listener.listen( |
132 | + (event) { | ||
104 | if (!_conditional(condition)) return; | 133 | if (!_conditional(condition)) return; |
105 | ref._disposed = true; | 134 | ref._disposed = true; |
106 | ref._log('called'); | 135 | ref._log('called'); |
107 | sub?.cancel(); | 136 | sub?.cancel(); |
108 | callback(event); | 137 | callback(event); |
109 | - }); | 138 | + }, |
139 | + onError: onError, | ||
140 | + onDone: onDone, | ||
141 | + cancelOnError: cancelOnError, | ||
142 | + ); | ||
110 | ref = Worker(sub.cancel, '[once]'); | 143 | ref = Worker(sub.cancel, '[once]'); |
111 | return ref; | 144 | return ref; |
112 | } | 145 | } |
@@ -128,17 +161,29 @@ Worker once<T>(RxInterface<T> listener, WorkerCallback<T> callback, | @@ -128,17 +161,29 @@ Worker once<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
128 | /// condition: () => count < 20, | 161 | /// condition: () => count < 20, |
129 | /// ); | 162 | /// ); |
130 | /// ``` | 163 | /// ``` |
131 | -Worker interval<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
132 | - {Duration time = const Duration(seconds: 1), dynamic condition = true}) { | 164 | +Worker interval<T>( |
165 | + RxInterface<T> listener, | ||
166 | + WorkerCallback<T> callback, { | ||
167 | + Duration time = const Duration(seconds: 1), | ||
168 | + dynamic condition = true, | ||
169 | + Function onError, | ||
170 | + void Function() onDone, | ||
171 | + bool cancelOnError, | ||
172 | +}) { | ||
133 | var debounceActive = false; | 173 | var debounceActive = false; |
134 | time ??= const Duration(seconds: 1); | 174 | time ??= const Duration(seconds: 1); |
135 | - StreamSubscription sub = listener.listen((event) async { | 175 | + StreamSubscription sub = listener.listen( |
176 | + (event) async { | ||
136 | if (debounceActive || !_conditional(condition)) return; | 177 | if (debounceActive || !_conditional(condition)) return; |
137 | debounceActive = true; | 178 | debounceActive = true; |
138 | await Future.delayed(time); | 179 | await Future.delayed(time); |
139 | debounceActive = false; | 180 | debounceActive = false; |
140 | callback(event); | 181 | callback(event); |
141 | - }); | 182 | + }, |
183 | + onError: onError, | ||
184 | + onDone: onDone, | ||
185 | + cancelOnError: cancelOnError, | ||
186 | + ); | ||
142 | return Worker(sub.cancel, '[interval]'); | 187 | return Worker(sub.cancel, '[interval]'); |
143 | } | 188 | } |
144 | 189 | ||
@@ -161,15 +206,26 @@ Worker interval<T>(RxInterface<T> listener, WorkerCallback<T> callback, | @@ -161,15 +206,26 @@ Worker interval<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
161 | /// ); | 206 | /// ); |
162 | /// } | 207 | /// } |
163 | /// ``` | 208 | /// ``` |
164 | -Worker debounce<T>(RxInterface<T> listener, WorkerCallback<T> callback, | ||
165 | - {Duration time}) { | 209 | +Worker debounce<T>( |
210 | + RxInterface<T> listener, | ||
211 | + WorkerCallback<T> callback, { | ||
212 | + Duration time, | ||
213 | + Function onError, | ||
214 | + void Function() onDone, | ||
215 | + bool cancelOnError, | ||
216 | +}) { | ||
166 | final _debouncer = | 217 | final _debouncer = |
167 | Debouncer(delay: time ?? const Duration(milliseconds: 800)); | 218 | Debouncer(delay: time ?? const Duration(milliseconds: 800)); |
168 | - StreamSubscription sub = listener.listen((event) { | 219 | + StreamSubscription sub = listener.listen( |
220 | + (event) { | ||
169 | _debouncer(() { | 221 | _debouncer(() { |
170 | callback(event); | 222 | callback(event); |
171 | }); | 223 | }); |
172 | - }); | 224 | + }, |
225 | + onError: onError, | ||
226 | + onDone: onDone, | ||
227 | + cancelOnError: cancelOnError, | ||
228 | + ); | ||
173 | return Worker(sub.cancel, '[debounce]'); | 229 | return Worker(sub.cancel, '[debounce]'); |
174 | } | 230 | } |
175 | 231 | ||
@@ -183,6 +239,8 @@ class Worker { | @@ -183,6 +239,8 @@ class Worker { | ||
183 | final String type; | 239 | final String type; |
184 | bool _disposed = false; | 240 | bool _disposed = false; |
185 | 241 | ||
242 | + bool get disposed => _disposed; | ||
243 | + | ||
186 | //final bool _verbose = true; | 244 | //final bool _verbose = true; |
187 | void _log(String msg) { | 245 | void _log(String msg) { |
188 | // if (!_verbose) return; | 246 | // if (!_verbose) return; |
@@ -53,18 +53,17 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> { | @@ -53,18 +53,17 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> { | ||
53 | 53 | ||
54 | @override | 54 | @override |
55 | void initState() { | 55 | void initState() { |
56 | - var isPrepared = GetInstance().isPrepared<T>(tag: widget.tag); | 56 | + // var isPrepared = GetInstance().isPrepared<T>(tag: widget.tag); |
57 | var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag); | 57 | var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag); |
58 | 58 | ||
59 | if (widget.global) { | 59 | if (widget.global) { |
60 | - if (isPrepared) { | ||
61 | - if (Get.smartManagement != SmartManagement.keepFactory) { | 60 | + if (isRegistered) { |
61 | + if (GetInstance().isPrepared<T>(tag: widget.tag)) { | ||
62 | isCreator = true; | 62 | isCreator = true; |
63 | + } else { | ||
64 | + isCreator = false; | ||
63 | } | 65 | } |
64 | controller = GetInstance().find<T>(tag: widget.tag); | 66 | controller = GetInstance().find<T>(tag: widget.tag); |
65 | - } else if (isRegistered) { | ||
66 | - controller = GetInstance().find<T>(tag: widget.tag); | ||
67 | - isCreator = false; | ||
68 | } else { | 67 | } else { |
69 | controller = widget.init; | 68 | controller = widget.init; |
70 | isCreator = true; | 69 | isCreator = true; |
@@ -75,7 +74,7 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> { | @@ -75,7 +74,7 @@ class GetXState<T extends DisposableInterface> extends State<GetX<T>> { | ||
75 | isCreator = true; | 74 | isCreator = true; |
76 | controller?.onStart(); | 75 | controller?.onStart(); |
77 | } | 76 | } |
78 | - if (widget.initState != null) widget.initState(this); | 77 | + widget.initState?.call(this); |
79 | if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) { | 78 | if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) { |
80 | controller?.onStart(); | 79 | controller?.onStart(); |
81 | } | 80 | } |
@@ -29,10 +29,16 @@ class _ObxState extends State<ObxWidget> { | @@ -29,10 +29,16 @@ class _ObxState extends State<ObxWidget> { | ||
29 | 29 | ||
30 | @override | 30 | @override |
31 | void initState() { | 31 | void initState() { |
32 | - subs = _observer.listen((data) => setState(() {})); | 32 | + subs = _observer.listen(_updateTree); |
33 | super.initState(); | 33 | super.initState(); |
34 | } | 34 | } |
35 | 35 | ||
36 | + void _updateTree(_) { | ||
37 | + if (mounted) { | ||
38 | + setState(() {}); | ||
39 | + } | ||
40 | + } | ||
41 | + | ||
36 | @override | 42 | @override |
37 | void dispose() { | 43 | void dispose() { |
38 | subs.cancel(); | 44 | subs.cancel(); |
1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
2 | -import '../../../get_core/get_core.dart'; | ||
3 | import '../../../get_instance/src/get_instance.dart'; | 2 | import '../../../get_instance/src/get_instance.dart'; |
4 | import '../../get_state_manager.dart'; | 3 | import '../../get_state_manager.dart'; |
5 | import 'list_notifier.dart'; | 4 | import 'list_notifier.dart'; |
@@ -89,19 +88,18 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -89,19 +88,18 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
89 | void initState() { | 88 | void initState() { |
90 | super.initState(); | 89 | super.initState(); |
91 | 90 | ||
92 | - if (widget.initState != null) widget.initState(this); | ||
93 | - if (widget.global) { | ||
94 | - final isPrepared = GetInstance().isPrepared<T>(tag: widget.tag); | ||
95 | - final isRegistered = GetInstance().isRegistered<T>(tag: widget.tag); | 91 | + widget.initState?.call(this); |
92 | + | ||
93 | + var isRegistered = GetInstance().isRegistered<T>(tag: widget.tag); | ||
96 | 94 | ||
97 | - if (isPrepared) { | ||
98 | - if (Get.smartManagement != SmartManagement.keepFactory) { | 95 | + if (widget.global) { |
96 | + if (isRegistered) { | ||
97 | + if (GetInstance().isPrepared<T>(tag: widget.tag)) { | ||
99 | isCreator = true; | 98 | isCreator = true; |
99 | + } else { | ||
100 | + isCreator = false; | ||
100 | } | 101 | } |
101 | controller = GetInstance().find<T>(tag: widget.tag); | 102 | controller = GetInstance().find<T>(tag: widget.tag); |
102 | - } else if (isRegistered) { | ||
103 | - controller = GetInstance().find<T>(tag: widget.tag); | ||
104 | - isCreator = false; | ||
105 | } else { | 103 | } else { |
106 | controller = widget.init; | 104 | controller = widget.init; |
107 | isCreator = true; | 105 | isCreator = true; |
@@ -160,36 +158,3 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | @@ -160,36 +158,3 @@ class _GetBuilderState<T extends GetxController> extends State<GetBuilder<T>> | ||
160 | @override | 158 | @override |
161 | Widget build(BuildContext context) => widget.builder(controller); | 159 | Widget build(BuildContext context) => widget.builder(controller); |
162 | } | 160 | } |
163 | - | ||
164 | -/// It's Experimental class, the Api can be change | ||
165 | -abstract class GetState<T> extends GetxController { | ||
166 | - GetState(T initialValue) { | ||
167 | - _state = initialValue; | ||
168 | - } | ||
169 | - | ||
170 | - // StreamController<T> _subject; | ||
171 | - | ||
172 | - // @override | ||
173 | - // void onClose() { | ||
174 | - // _subject?.close(); | ||
175 | - // } | ||
176 | - | ||
177 | - // Stream<T> get stream { | ||
178 | - // if (_subject == null) { | ||
179 | - // _subject = StreamController<T>.broadcast(); | ||
180 | - // } | ||
181 | - // return _subject.stream; | ||
182 | - // } | ||
183 | - | ||
184 | - T _state; | ||
185 | - | ||
186 | - T get state => _state; | ||
187 | - | ||
188 | - @protected | ||
189 | - void change(T newState) { | ||
190 | - if (newState != _state) { | ||
191 | - _state = newState; | ||
192 | - update(); | ||
193 | - } | ||
194 | - } | ||
195 | -} |
1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; |
2 | -import '../../../get_instance/src/get_instance.dart'; | 2 | + |
3 | import '../../../instance_manager.dart'; | 3 | import '../../../instance_manager.dart'; |
4 | +import '../../../utils.dart'; | ||
4 | import 'get_widget_cache.dart'; | 5 | import 'get_widget_cache.dart'; |
5 | 6 | ||
6 | /// GetView is a great way of quickly access your Controller | 7 | /// GetView is a great way of quickly access your Controller |
@@ -40,25 +41,6 @@ abstract class GetView<T> extends StatelessWidget { | @@ -40,25 +41,6 @@ abstract class GetView<T> extends StatelessWidget { | ||
40 | Widget build(BuildContext context); | 41 | Widget build(BuildContext context); |
41 | } | 42 | } |
42 | 43 | ||
43 | -// abstract class GetView<A, B> extends StatelessWidget { | ||
44 | -// const GetView({Key key}) : super(key: key); | ||
45 | -// A get controller => GetInstance().find(); | ||
46 | -// B get controller2 => GetInstance().find(); | ||
47 | - | ||
48 | -// @override | ||
49 | -// Widget build(BuildContext context); | ||
50 | -// } | ||
51 | - | ||
52 | -// abstract class GetView2<A, B, C> extends StatelessWidget { | ||
53 | -// const GetView2({Key key}) : super(key: key); | ||
54 | -// A get controller => GetInstance().find(); | ||
55 | -// B get controller2 => GetInstance().find(); | ||
56 | -// C get controller3 => GetInstance().find(); | ||
57 | - | ||
58 | -// @override | ||
59 | -// Widget build(BuildContext context); | ||
60 | -// } | ||
61 | - | ||
62 | /// GetWidget is a great way of quickly access your individual Controller | 44 | /// GetWidget is a great way of quickly access your individual Controller |
63 | /// without having to call Get.find<AwesomeController>() yourself. | 45 | /// without having to call Get.find<AwesomeController>() yourself. |
64 | /// Get save you controller on cache, so, you can to use Get.create() safely | 46 | /// Get save you controller on cache, so, you can to use Get.create() safely |
@@ -73,7 +55,9 @@ abstract class GetWidget<S extends GetLifeCycleBase> extends GetWidgetCache { | @@ -73,7 +55,9 @@ abstract class GetWidget<S extends GetLifeCycleBase> extends GetWidgetCache { | ||
73 | 55 | ||
74 | S get controller => GetWidget._cache[this] as S; | 56 | S get controller => GetWidget._cache[this] as S; |
75 | 57 | ||
76 | - static final _cache = <GetWidget, GetLifeCycleBase>{}; | 58 | + // static final _cache = <GetWidget, GetLifeCycleBase>{}; |
59 | + | ||
60 | + static final _cache = Expando<GetLifeCycleBase>(); | ||
77 | 61 | ||
78 | @protected | 62 | @protected |
79 | Widget build(BuildContext context); | 63 | Widget build(BuildContext context); |
@@ -84,8 +68,10 @@ abstract class GetWidget<S extends GetLifeCycleBase> extends GetWidgetCache { | @@ -84,8 +68,10 @@ abstract class GetWidget<S extends GetLifeCycleBase> extends GetWidgetCache { | ||
84 | 68 | ||
85 | class _GetCache<S extends GetLifeCycleBase> extends WidgetCache<GetWidget<S>> { | 69 | class _GetCache<S extends GetLifeCycleBase> extends WidgetCache<GetWidget<S>> { |
86 | S _controller; | 70 | S _controller; |
71 | + bool _isCreator = false; | ||
87 | @override | 72 | @override |
88 | void onInit() { | 73 | void onInit() { |
74 | + _isCreator = Get.isPrepared<S>(tag: widget.tag); | ||
89 | _controller = Get.find<S>(tag: widget.tag); | 75 | _controller = Get.find<S>(tag: widget.tag); |
90 | GetWidget._cache[widget] = _controller; | 76 | GetWidget._cache[widget] = _controller; |
91 | super.onInit(); | 77 | super.onInit(); |
@@ -93,7 +79,14 @@ class _GetCache<S extends GetLifeCycleBase> extends WidgetCache<GetWidget<S>> { | @@ -93,7 +79,14 @@ class _GetCache<S extends GetLifeCycleBase> extends WidgetCache<GetWidget<S>> { | ||
93 | 79 | ||
94 | @override | 80 | @override |
95 | void onClose() { | 81 | void onClose() { |
96 | - GetWidget._cache.remove(widget); | 82 | + if (_isCreator) { |
83 | + Get.asap(() { | ||
84 | + widget.controller.onDelete(); | ||
85 | + Get.log('"${widget.controller.runtimeType}" onClose() called'); | ||
86 | + Get.log('"${widget.controller.runtimeType}" deleted from memory'); | ||
87 | + GetWidget._cache[widget] = null; | ||
88 | + }); | ||
89 | + } | ||
97 | super.onClose(); | 90 | super.onClose(); |
98 | } | 91 | } |
99 | 92 |
1 | import '../get_utils/get_utils.dart'; | 1 | import '../get_utils/get_utils.dart'; |
2 | 2 | ||
3 | -extension GetDynamicUtils on dynamic { | 3 | +extension GetDynamicUtils<T> on T { |
4 | @Deprecated('isNull is deprecated and cannot be used, use "==" operator') | 4 | @Deprecated('isNull is deprecated and cannot be used, use "==" operator') |
5 | bool get isNull => GetUtils.isNull(this); | 5 | bool get isNull => GetUtils.isNull(this); |
6 | 6 |
@@ -103,12 +103,13 @@ void main() { | @@ -103,12 +103,13 @@ void main() { | ||
103 | tearDownAll(Get.reset); | 103 | tearDownAll(Get.reset); |
104 | 104 | ||
105 | test('Get.put test with init check', () async { | 105 | test('Get.put test with init check', () async { |
106 | - final instance = Get.put<DisposableController>(DisposableController()); | 106 | + final instance = Get.put(DisposableController()); |
107 | expect(instance, Get.find<DisposableController>()); | 107 | expect(instance, Get.find<DisposableController>()); |
108 | expect(instance.initialized, true); | 108 | expect(instance.initialized, true); |
109 | }); | 109 | }); |
110 | 110 | ||
111 | test('Get.delete test with disposable controller', () async { | 111 | test('Get.delete test with disposable controller', () async { |
112 | + // Get.put(DisposableController()); | ||
112 | expect(await Get.delete<DisposableController>(), true); | 113 | expect(await Get.delete<DisposableController>(), true); |
113 | expect(() => Get.find<DisposableController>(), | 114 | expect(() => Get.find<DisposableController>(), |
114 | throwsA(m.TypeMatcher<String>())); | 115 | throwsA(m.TypeMatcher<String>())); |
-
Please register or login to post a comment