Committed by
GitHub
Merge pull request #2095 from jonataslaw/sm-refactor
Sm refactor
Showing
23 changed files
with
697 additions
and
734 deletions
@@ -3,7 +3,7 @@ import 'package:get/get.dart'; | @@ -3,7 +3,7 @@ import 'package:get/get.dart'; | ||
3 | import '../../domain/adapters/repository_adapter.dart'; | 3 | import '../../domain/adapters/repository_adapter.dart'; |
4 | import '../../domain/entity/cases_model.dart'; | 4 | import '../../domain/entity/cases_model.dart'; |
5 | 5 | ||
6 | -class HomeController extends SuperController<CasesModel> { | 6 | +class HomeController extends StateController<CasesModel> { |
7 | HomeController({required this.homeRepository}); | 7 | HomeController({required this.homeRepository}); |
8 | 8 | ||
9 | final IHomeRepository homeRepository; | 9 | final IHomeRepository homeRepository; |
@@ -11,74 +11,12 @@ class HomeController extends SuperController<CasesModel> { | @@ -11,74 +11,12 @@ class HomeController extends SuperController<CasesModel> { | ||
11 | @override | 11 | @override |
12 | void onInit() { | 12 | void onInit() { |
13 | super.onInit(); | 13 | super.onInit(); |
14 | - | ||
15 | //Loading, Success, Error handle with 1 line of code | 14 | //Loading, Success, Error handle with 1 line of code |
16 | - append(() => homeRepository.getCases); | 15 | + futurize(() => homeRepository.getCases); |
17 | } | 16 | } |
18 | 17 | ||
19 | Country getCountryById(String id) { | 18 | Country getCountryById(String id) { |
20 | final index = int.tryParse(id); | 19 | final index = int.tryParse(id); |
21 | - if (index != null) { | ||
22 | - return state.countries[index]; | ||
23 | - } | ||
24 | - | ||
25 | - return state.countries.first; | ||
26 | - } | ||
27 | - | ||
28 | - @override | ||
29 | - void onReady() { | ||
30 | - print('The build method is done. ' | ||
31 | - 'Your controller is ready to call dialogs and snackbars'); | ||
32 | - super.onReady(); | ||
33 | - } | ||
34 | - | ||
35 | - @override | ||
36 | - void onClose() { | ||
37 | - print('onClose called'); | ||
38 | - super.onClose(); | ||
39 | - } | ||
40 | - | ||
41 | - @override | ||
42 | - void didChangeMetrics() { | ||
43 | - print('the window size did change'); | ||
44 | - super.didChangeMetrics(); | ||
45 | - } | ||
46 | - | ||
47 | - @override | ||
48 | - void didChangePlatformBrightness() { | ||
49 | - print('platform change ThemeMode'); | ||
50 | - super.didChangePlatformBrightness(); | ||
51 | - } | ||
52 | - | ||
53 | - @override | ||
54 | - Future<bool> didPushRoute(String route) { | ||
55 | - print('the route $route will be open'); | ||
56 | - return super.didPushRoute(route); | ||
57 | - } | ||
58 | - | ||
59 | - @override | ||
60 | - Future<bool> didPopRoute() { | ||
61 | - print('the current route will be closed'); | ||
62 | - return super.didPopRoute(); | ||
63 | - } | ||
64 | - | ||
65 | - @override | ||
66 | - void onDetached() { | ||
67 | - print('onDetached called'); | ||
68 | - } | ||
69 | - | ||
70 | - @override | ||
71 | - void onInactive() { | ||
72 | - print('onInative called'); | ||
73 | - } | ||
74 | - | ||
75 | - @override | ||
76 | - void onPaused() { | ||
77 | - print('onPaused called'); | ||
78 | - } | ||
79 | - | ||
80 | - @override | ||
81 | - void onResumed() { | ||
82 | - print('onResumed called'); | 20 | + return index != null ? state.countries[index] : state.countries.first; |
83 | } | 21 | } |
84 | } | 22 | } |
1 | import 'dart:io'; | 1 | import 'dart:io'; |
2 | -import 'dart:math'; | ||
3 | 2 | ||
4 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
5 | import 'package:flutter_test/flutter_test.dart'; | 4 | import 'package:flutter_test/flutter_test.dart'; |
@@ -11,28 +10,29 @@ import 'package:get_demo/pages/home/presentation/controllers/home_controller.dar | @@ -11,28 +10,29 @@ import 'package:get_demo/pages/home/presentation/controllers/home_controller.dar | ||
11 | // import 'package:get_test/get_test.dart'; | 10 | // import 'package:get_test/get_test.dart'; |
12 | import 'package:matcher/matcher.dart' as m; | 11 | import 'package:matcher/matcher.dart' as m; |
13 | 12 | ||
14 | -class MockRepository implements IHomeRepository { | 13 | +class MockRepositorySuccess implements IHomeRepository { |
15 | @override | 14 | @override |
16 | Future<CasesModel> getCases() async { | 15 | Future<CasesModel> getCases() async { |
17 | - await Future.delayed(Duration(milliseconds: 100)); | ||
18 | - | ||
19 | - if (Random().nextBool()) { | ||
20 | - return CasesModel( | ||
21 | - global: Global( | ||
22 | - totalDeaths: 100, | ||
23 | - totalConfirmed: 200, | ||
24 | - date: DateTime.now(), | ||
25 | - newConfirmed: 0, | ||
26 | - newDeaths: 0, | ||
27 | - newRecovered: 0, | ||
28 | - totalRecovered: 0), | ||
29 | - countries: [], | ||
30 | - date: DateTime.now(), | ||
31 | - id: '', | ||
32 | - message: '', | ||
33 | - ); | ||
34 | - } | 16 | + return CasesModel( |
17 | + global: Global( | ||
18 | + totalDeaths: 100, | ||
19 | + totalConfirmed: 200, | ||
20 | + date: DateTime.now(), | ||
21 | + newConfirmed: 0, | ||
22 | + newDeaths: 0, | ||
23 | + newRecovered: 0, | ||
24 | + totalRecovered: 0), | ||
25 | + countries: [], | ||
26 | + date: DateTime.now(), | ||
27 | + id: '', | ||
28 | + message: '', | ||
29 | + ); | ||
30 | + } | ||
31 | +} | ||
35 | 32 | ||
33 | +class MockRepositoryFailure implements IHomeRepository { | ||
34 | + @override | ||
35 | + Future<CasesModel> getCases() async { | ||
36 | return Future<CasesModel>.error('error'); | 36 | return Future<CasesModel>.error('error'); |
37 | } | 37 | } |
38 | } | 38 | } |
@@ -41,28 +41,18 @@ void main() { | @@ -41,28 +41,18 @@ void main() { | ||
41 | WidgetsFlutterBinding.ensureInitialized(); | 41 | WidgetsFlutterBinding.ensureInitialized(); |
42 | setUpAll(() => HttpOverrides.global = null); | 42 | setUpAll(() => HttpOverrides.global = null); |
43 | final binding = BindingsBuilder(() { | 43 | final binding = BindingsBuilder(() { |
44 | - Get.lazyPut<IHomeRepository>(() => MockRepository()); | 44 | + Get.lazyPut<IHomeRepository>(() => MockRepositorySuccess()); |
45 | Get.lazyPut<HomeController>( | 45 | Get.lazyPut<HomeController>( |
46 | - () => HomeController(homeRepository: Get.find())); | 46 | + () => HomeController(homeRepository: Get.find()), |
47 | + ); | ||
47 | }); | 48 | }); |
48 | 49 | ||
49 | - test('Test Binding', () { | ||
50 | - expect(Get.isPrepared<HomeController>(), false); | ||
51 | - expect(Get.isPrepared<IHomeRepository>(), false); | ||
52 | - | ||
53 | - /// test you Binding class with BindingsBuilder | ||
54 | - binding.builder(); | ||
55 | - | ||
56 | - expect(Get.isPrepared<HomeController>(), true); | ||
57 | - expect(Get.isPrepared<IHomeRepository>(), true); | ||
58 | - | ||
59 | - Get.reset(); | ||
60 | - }); | ||
61 | test('Test Controller', () async { | 50 | test('Test Controller', () async { |
62 | /// Controller can't be on memory | 51 | /// Controller can't be on memory |
63 | - expect(() => Get.find<HomeController>(), throwsA(m.TypeMatcher<String>())); | 52 | + expect(() => Get.find<HomeController>(tag: 'success'), |
53 | + throwsA(m.TypeMatcher<String>())); | ||
64 | 54 | ||
65 | - /// build Binding | 55 | + /// binding will put the controller on memory |
66 | binding.builder(); | 56 | binding.builder(); |
67 | 57 | ||
68 | /// recover your controller | 58 | /// recover your controller |
@@ -77,24 +67,15 @@ void main() { | @@ -77,24 +67,15 @@ void main() { | ||
77 | /// await time request | 67 | /// await time request |
78 | await Future.delayed(Duration(milliseconds: 100)); | 68 | await Future.delayed(Duration(milliseconds: 100)); |
79 | 69 | ||
80 | - if (controller.status.isError) { | ||
81 | - expect(controller.state, null); | ||
82 | - } | ||
83 | - | ||
84 | - if (controller.status.isSuccess) { | ||
85 | - expect(controller.state.global.totalDeaths, 100); | ||
86 | - expect(controller.state.global.totalConfirmed, 200); | ||
87 | - } | ||
88 | - }); | 70 | + /// test if status is success |
71 | + expect(controller.status.isSuccess, true); | ||
72 | + expect(controller.state.global.totalDeaths, 100); | ||
73 | + expect(controller.state.global.totalConfirmed, 200); | ||
89 | 74 | ||
90 | - test('ever', () async { | ||
91 | - final count = ''.obs; | ||
92 | - var result = ''; | ||
93 | - ever<String>(count, (value) { | ||
94 | - result = value; | ||
95 | - }); | ||
96 | - count.value = '1'; | ||
97 | - expect('1', result); | 75 | + /// test if status is error |
76 | + Get.lazyReplace<IHomeRepository>(() => MockRepositoryFailure()); | ||
77 | + expect(controller.status.isError, true); | ||
78 | + expect(controller.state, null); | ||
98 | }); | 79 | }); |
99 | 80 | ||
100 | /// Tests with GetTests | 81 | /// Tests with GetTests |
@@ -151,26 +132,3 @@ void main() { | @@ -151,26 +132,3 @@ void main() { | ||
151 | }, | 132 | }, |
152 | );*/ | 133 | );*/ |
153 | } | 134 | } |
154 | - | ||
155 | -class Controller extends GetxController { | ||
156 | - final count = 0.obs; | ||
157 | - void increment() => count.value++; | ||
158 | - | ||
159 | - @override | ||
160 | - void onInit() { | ||
161 | - print('inittt'); | ||
162 | - super.onInit(); | ||
163 | - } | ||
164 | - | ||
165 | - @override | ||
166 | - void onReady() { | ||
167 | - print('onReady'); | ||
168 | - super.onReady(); | ||
169 | - } | ||
170 | - | ||
171 | - @override | ||
172 | - void onClose() { | ||
173 | - super.onClose(); | ||
174 | - print('onClose'); | ||
175 | - } | ||
176 | -} |
example/test/widget_test.dart
0 → 100644
@@ -21,6 +21,6 @@ | @@ -21,6 +21,6 @@ | ||
21 | <key>CFBundleVersion</key> | 21 | <key>CFBundleVersion</key> |
22 | <string>1.0</string> | 22 | <string>1.0</string> |
23 | <key>MinimumOSVersion</key> | 23 | <key>MinimumOSVersion</key> |
24 | - <string>8.0</string> | 24 | + <string>9.0</string> |
25 | </dict> | 25 | </dict> |
26 | </plist> | 26 | </plist> |
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | archiveVersion = 1; | 3 | archiveVersion = 1; |
4 | classes = { | 4 | classes = { |
5 | }; | 5 | }; |
6 | - objectVersion = 46; | 6 | + objectVersion = 50; |
7 | objects = { | 7 | objects = { |
8 | 8 | ||
9 | /* Begin PBXBuildFile section */ | 9 | /* Begin PBXBuildFile section */ |
@@ -127,7 +127,7 @@ | @@ -127,7 +127,7 @@ | ||
127 | 97C146E61CF9000F007C117D /* Project object */ = { | 127 | 97C146E61CF9000F007C117D /* Project object */ = { |
128 | isa = PBXProject; | 128 | isa = PBXProject; |
129 | attributes = { | 129 | attributes = { |
130 | - LastUpgradeCheck = 1020; | 130 | + LastUpgradeCheck = 1300; |
131 | ORGANIZATIONNAME = ""; | 131 | ORGANIZATIONNAME = ""; |
132 | TargetAttributes = { | 132 | TargetAttributes = { |
133 | 97C146ED1CF9000F007C117D = { | 133 | 97C146ED1CF9000F007C117D = { |
@@ -6,7 +6,8 @@ import 'package:flutter/material.dart'; | @@ -6,7 +6,8 @@ import 'package:flutter/material.dart'; | ||
6 | import '../../../get.dart'; | 6 | import '../../../get.dart'; |
7 | import '../../../get_state_manager/src/simple/list_notifier.dart'; | 7 | import '../../../get_state_manager/src/simple/list_notifier.dart'; |
8 | 8 | ||
9 | -class GetDelegate extends RouterDelegate<GetNavConfig> with ListNotifierMixin { | 9 | +class GetDelegate extends RouterDelegate<GetNavConfig> |
10 | + with ListNotifierSingleMixin { | ||
10 | final List<GetNavConfig> history = <GetNavConfig>[]; | 11 | final List<GetNavConfig> history = <GetNavConfig>[]; |
11 | final PopMode backButtonPopMode; | 12 | final PopMode backButtonPopMode; |
12 | final PreventDuplicateHandlingMode preventDuplicateHandlingMode; | 13 | final PreventDuplicateHandlingMode preventDuplicateHandlingMode; |
1 | -part of rx_stream; | ||
2 | - | ||
3 | -/// [GetStream] is the lightest and most performative way of working | ||
4 | -/// with events at Dart. You sintaxe is like StreamController, but it works | ||
5 | -/// with simple callbacks. In this way, every event calls only one function. | ||
6 | -/// There is no buffering, to very low memory consumption. | ||
7 | -/// event [add] will add a object to stream. [addError] will add a error | ||
8 | -/// to stream. [listen] is a very light StreamSubscription interface. | ||
9 | -/// Is possible take the last value with [value] property. | ||
10 | -class GetStream<T> { | ||
11 | - void Function()? onListen; | ||
12 | - void Function()? onPause; | ||
13 | - void Function()? onResume; | ||
14 | - FutureOr<void> Function()? onCancel; | ||
15 | - | ||
16 | - GetStream({this.onListen, this.onPause, this.onResume, this.onCancel}); | ||
17 | - | ||
18 | - factory GetStream.fromValue(T value, | ||
19 | - {Function()? onListen, | ||
20 | - Function()? onPause, | ||
21 | - Function()? onResume, | ||
22 | - FutureOr<void> Function()? onCancel}) { | ||
23 | - final valuedStream = GetStream<T>( | ||
24 | - onListen: onListen, | ||
25 | - onPause: onPause, | ||
26 | - onResume: onResume, | ||
27 | - onCancel: onCancel) | ||
28 | - .._value = value; | ||
29 | - | ||
30 | - return valuedStream; | ||
31 | - } | ||
32 | - | ||
33 | - List<LightSubscription<T>>? _onData = <LightSubscription<T>>[]; | ||
34 | - | ||
35 | - bool? _isBusy = false; | ||
36 | - | ||
37 | - FutureOr<bool?> removeSubscription(LightSubscription<T> subs) async { | ||
38 | - if (!_isBusy!) { | ||
39 | - return _onData!.remove(subs); | ||
40 | - } else { | ||
41 | - await Future.delayed(Duration.zero); | ||
42 | - return _onData?.remove(subs); | ||
43 | - } | ||
44 | - } | ||
45 | - | ||
46 | - FutureOr<void> addSubscription(LightSubscription<T> subs) async { | ||
47 | - if (!_isBusy!) { | ||
48 | - return _onData!.add(subs); | ||
49 | - } else { | ||
50 | - await Future.delayed(Duration.zero); | ||
51 | - return _onData!.add(subs); | ||
52 | - } | ||
53 | - } | ||
54 | - | ||
55 | - int? get length => _onData?.length; | ||
56 | - | ||
57 | - bool get hasListeners => _onData!.isNotEmpty; | ||
58 | - | ||
59 | - void _notifyData(T data) { | ||
60 | - _isBusy = true; | ||
61 | - for (final item in _onData!) { | ||
62 | - if (!item.isPaused) { | ||
63 | - item._data?.call(data); | ||
64 | - } | ||
65 | - } | ||
66 | - _isBusy = false; | ||
67 | - } | ||
68 | - | ||
69 | - void _notifyError(Object error, [StackTrace? stackTrace]) { | ||
70 | - assert(!isClosed, 'You cannot add errors to a closed stream.'); | ||
71 | - _isBusy = true; | ||
72 | - var itemsToRemove = <LightSubscription<T>>[]; | ||
73 | - for (final item in _onData!) { | ||
74 | - if (!item.isPaused) { | ||
75 | - if (stackTrace != null) { | ||
76 | - item._onError?.call(error, stackTrace); | ||
77 | - } else { | ||
78 | - item._onError?.call(error); | ||
79 | - } | ||
80 | - | ||
81 | - if (item.cancelOnError ?? false) { | ||
82 | - //item.cancel?.call(); | ||
83 | - itemsToRemove.add(item); | ||
84 | - item.pause(); | ||
85 | - item._onDone?.call(); | ||
86 | - } | ||
87 | - } | ||
88 | - } | ||
89 | - for (final item in itemsToRemove) { | ||
90 | - _onData!.remove(item); | ||
91 | - } | ||
92 | - _isBusy = false; | ||
93 | - } | ||
94 | - | ||
95 | - void _notifyDone() { | ||
96 | - assert(!isClosed, 'You cannot close a closed stream.'); | ||
97 | - _isBusy = true; | ||
98 | - for (final item in _onData!) { | ||
99 | - if (!item.isPaused) { | ||
100 | - item._onDone?.call(); | ||
101 | - } | ||
102 | - } | ||
103 | - _isBusy = false; | ||
104 | - } | ||
105 | - | ||
106 | - late T _value; | ||
107 | - | ||
108 | - T get value { | ||
109 | - RxInterface.proxy?.addListener(this); | ||
110 | - return _value; | ||
111 | - } | ||
112 | - | ||
113 | - void add(T event) { | ||
114 | - assert(!isClosed, 'You cannot add event to closed Stream'); | ||
115 | - _value = event; | ||
116 | - _notifyData(event); | ||
117 | - } | ||
118 | - | ||
119 | - bool get isClosed => _onData == null; | ||
120 | - | ||
121 | - void addError(Object error, [StackTrace? stackTrace]) { | ||
122 | - assert(!isClosed, 'You cannot add error to closed Stream'); | ||
123 | - _notifyError(error, stackTrace); | ||
124 | - } | ||
125 | - | ||
126 | - void close() { | ||
127 | - assert(!isClosed, 'You cannot close a closed Stream'); | ||
128 | - _notifyDone(); | ||
129 | - _onData = null; | ||
130 | - _isBusy = null; | ||
131 | - // _value = null; | ||
132 | - } | ||
133 | - | ||
134 | - LightSubscription<T> listen(void Function(T event) onData, | ||
135 | - {Function? onError, void Function()? onDone, bool? cancelOnError}) { | ||
136 | - final subs = LightSubscription<T>( | ||
137 | - removeSubscription, | ||
138 | - onPause: onPause, | ||
139 | - onResume: onResume, | ||
140 | - onCancel: onCancel, | ||
141 | - ) | ||
142 | - ..onData(onData) | ||
143 | - ..onError(onError) | ||
144 | - ..onDone(onDone) | ||
145 | - ..cancelOnError = cancelOnError; | ||
146 | - addSubscription(subs); | ||
147 | - onListen?.call(); | ||
148 | - return subs; | ||
149 | - } | ||
150 | - | ||
151 | - Stream<T> get stream => | ||
152 | - GetStreamTransformation(addSubscription, removeSubscription); | ||
153 | -} | ||
154 | - | ||
155 | -class LightSubscription<T> extends StreamSubscription<T> { | ||
156 | - final RemoveSubscription<T> _removeSubscription; | ||
157 | - LightSubscription(this._removeSubscription, | ||
158 | - {this.onPause, this.onResume, this.onCancel}); | ||
159 | - final void Function()? onPause; | ||
160 | - final void Function()? onResume; | ||
161 | - final FutureOr<void> Function()? onCancel; | ||
162 | - | ||
163 | - bool? cancelOnError = false; | ||
164 | - | ||
165 | - @override | ||
166 | - Future<void> cancel() { | ||
167 | - _removeSubscription(this); | ||
168 | - onCancel?.call(); | ||
169 | - return Future.value(); | ||
170 | - } | ||
171 | - | ||
172 | - OnData<T>? _data; | ||
173 | - | ||
174 | - Function? _onError; | ||
175 | - | ||
176 | - Callback? _onDone; | ||
177 | - | ||
178 | - bool _isPaused = false; | ||
179 | - | ||
180 | - @override | ||
181 | - void onData(OnData<T>? handleData) => _data = handleData; | ||
182 | - | ||
183 | - @override | ||
184 | - void onError(Function? handleError) => _onError = handleError; | ||
185 | - | ||
186 | - @override | ||
187 | - void onDone(Callback? handleDone) => _onDone = handleDone; | ||
188 | - | ||
189 | - @override | ||
190 | - void pause([Future<void>? resumeSignal]) { | ||
191 | - _isPaused = true; | ||
192 | - onPause?.call(); | ||
193 | - } | ||
194 | - | ||
195 | - @override | ||
196 | - void resume() { | ||
197 | - _isPaused = false; | ||
198 | - onResume?.call(); | ||
199 | - } | ||
200 | - | ||
201 | - @override | ||
202 | - bool get isPaused => _isPaused; | ||
203 | - | ||
204 | - @override | ||
205 | - Future<E> asFuture<E>([E? futureValue]) => Future.value(futureValue); | ||
206 | -} | ||
207 | - | ||
208 | -class GetStreamTransformation<T> extends Stream<T> { | ||
209 | - final AddSubscription<T> _addSubscription; | ||
210 | - final RemoveSubscription<T> _removeSubscription; | ||
211 | - GetStreamTransformation(this._addSubscription, this._removeSubscription); | ||
212 | - | ||
213 | - @override | ||
214 | - LightSubscription<T> listen(void Function(T event)? onData, | ||
215 | - {Function? onError, void Function()? onDone, bool? cancelOnError}) { | ||
216 | - final subs = LightSubscription<T>(_removeSubscription) | ||
217 | - ..onData(onData) | ||
218 | - ..onError(onError) | ||
219 | - ..onDone(onDone); | ||
220 | - _addSubscription(subs); | ||
221 | - return subs; | ||
222 | - } | ||
223 | -} | ||
224 | - | ||
225 | -typedef RemoveSubscription<T> = FutureOr<bool?> Function( | ||
226 | - LightSubscription<T> subs); | ||
227 | - | ||
228 | -typedef AddSubscription<T> = FutureOr<void> Function(LightSubscription<T> subs); | 1 | +// part of rx_stream; |
2 | + | ||
3 | +// /// [GetStream] is the lightest and most performative way of working | ||
4 | +// /// with events at Dart. You sintaxe is like StreamController, but it works | ||
5 | +// /// with simple callbacks. In this way, every event calls only one function. | ||
6 | +// /// There is no buffering, to very low memory consumption. | ||
7 | +// /// event [add] will add a object to stream. [addError] will add a error | ||
8 | +// /// to stream. [listen] is a very light StreamSubscription interface. | ||
9 | +// /// Is possible take the last value with [value] property. | ||
10 | +// class GetStream<T> { | ||
11 | +// void Function()? onListen; | ||
12 | +// void Function()? onPause; | ||
13 | +// void Function()? onResume; | ||
14 | +// FutureOr<void> Function()? onCancel; | ||
15 | + | ||
16 | +// GetStream({this.onListen, this.onPause, this.onResume, this.onCancel}); | ||
17 | + | ||
18 | +// factory GetStream.fromValue(T value, | ||
19 | +// {Function()? onListen, | ||
20 | +// Function()? onPause, | ||
21 | +// Function()? onResume, | ||
22 | +// FutureOr<void> Function()? onCancel}) { | ||
23 | +// final valuedStream = GetStream<T>( | ||
24 | +// onListen: onListen, | ||
25 | +// onPause: onPause, | ||
26 | +// onResume: onResume, | ||
27 | +// onCancel: onCancel) | ||
28 | +// .._value = value; | ||
29 | + | ||
30 | +// return valuedStream; | ||
31 | +// } | ||
32 | + | ||
33 | +// List<LightSubscription<T>>? _onData = <LightSubscription<T>>[]; | ||
34 | + | ||
35 | +// bool? _isBusy = false; | ||
36 | + | ||
37 | +// FutureOr<bool?> removeSubscription(LightSubscription<T> subs) async { | ||
38 | +// if (!_isBusy!) { | ||
39 | +// return _onData!.remove(subs); | ||
40 | +// } else { | ||
41 | +// await Future.delayed(Duration.zero); | ||
42 | +// return _onData?.remove(subs); | ||
43 | +// } | ||
44 | +// } | ||
45 | + | ||
46 | +// FutureOr<void> addSubscription(LightSubscription<T> subs) async { | ||
47 | +// if (!_isBusy!) { | ||
48 | +// return _onData!.add(subs); | ||
49 | +// } else { | ||
50 | +// await Future.delayed(Duration.zero); | ||
51 | +// return _onData!.add(subs); | ||
52 | +// } | ||
53 | +// } | ||
54 | + | ||
55 | +// int? get length => _onData?.length; | ||
56 | + | ||
57 | +// bool get hasListeners => _onData!.isNotEmpty; | ||
58 | + | ||
59 | +// void _notifyData(T data) { | ||
60 | +// _isBusy = true; | ||
61 | +// for (final item in _onData!) { | ||
62 | +// if (!item.isPaused) { | ||
63 | +// item._data?.call(data); | ||
64 | +// } | ||
65 | +// } | ||
66 | +// _isBusy = false; | ||
67 | +// } | ||
68 | + | ||
69 | +// void _notifyError(Object error, [StackTrace? stackTrace]) { | ||
70 | +// assert(!isClosed, 'You cannot add errors to a closed stream.'); | ||
71 | +// _isBusy = true; | ||
72 | +// var itemsToRemove = <LightSubscription<T>>[]; | ||
73 | +// for (final item in _onData!) { | ||
74 | +// if (!item.isPaused) { | ||
75 | +// if (stackTrace != null) { | ||
76 | +// item._onError?.call(error, stackTrace); | ||
77 | +// } else { | ||
78 | +// item._onError?.call(error); | ||
79 | +// } | ||
80 | + | ||
81 | +// if (item.cancelOnError ?? false) { | ||
82 | +// //item.cancel?.call(); | ||
83 | +// itemsToRemove.add(item); | ||
84 | +// item.pause(); | ||
85 | +// item._onDone?.call(); | ||
86 | +// } | ||
87 | +// } | ||
88 | +// } | ||
89 | +// for (final item in itemsToRemove) { | ||
90 | +// _onData!.remove(item); | ||
91 | +// } | ||
92 | +// _isBusy = false; | ||
93 | +// } | ||
94 | + | ||
95 | +// void _notifyDone() { | ||
96 | +// assert(!isClosed, 'You cannot close a closed stream.'); | ||
97 | +// _isBusy = true; | ||
98 | +// for (final item in _onData!) { | ||
99 | +// if (!item.isPaused) { | ||
100 | +// item._onDone?.call(); | ||
101 | +// } | ||
102 | +// } | ||
103 | +// _isBusy = false; | ||
104 | +// } | ||
105 | + | ||
106 | +// late T _value; | ||
107 | + | ||
108 | +// T get value { | ||
109 | +// // RxInterface.proxy?.addListener(this); | ||
110 | +// return _value; | ||
111 | +// } | ||
112 | + | ||
113 | +// void add(T event) { | ||
114 | +// assert(!isClosed, 'You cannot add event to closed Stream'); | ||
115 | +// _value = event; | ||
116 | +// _notifyData(event); | ||
117 | +// } | ||
118 | + | ||
119 | +// bool get isClosed => _onData == null; | ||
120 | + | ||
121 | +// void addError(Object error, [StackTrace? stackTrace]) { | ||
122 | +// assert(!isClosed, 'You cannot add error to closed Stream'); | ||
123 | +// _notifyError(error, stackTrace); | ||
124 | +// } | ||
125 | + | ||
126 | +// void close() { | ||
127 | +// assert(!isClosed, 'You cannot close a closed Stream'); | ||
128 | +// _notifyDone(); | ||
129 | +// _onData = null; | ||
130 | +// _isBusy = null; | ||
131 | +// // _value = null; | ||
132 | +// } | ||
133 | + | ||
134 | +// LightSubscription<T> listen(void Function(T event) onData, | ||
135 | +// {Function? onError, void Function()? onDone, bool? cancelOnError}) { | ||
136 | +// final subs = LightSubscription<T>( | ||
137 | +// removeSubscription, | ||
138 | +// onPause: onPause, | ||
139 | +// onResume: onResume, | ||
140 | +// onCancel: onCancel, | ||
141 | +// ) | ||
142 | +// ..onData(onData) | ||
143 | +// ..onError(onError) | ||
144 | +// ..onDone(onDone) | ||
145 | +// ..cancelOnError = cancelOnError; | ||
146 | +// addSubscription(subs); | ||
147 | +// onListen?.call(); | ||
148 | +// return subs; | ||
149 | +// } | ||
150 | + | ||
151 | +// Stream<T> get stream => | ||
152 | +// GetStreamTransformation(addSubscription, removeSubscription); | ||
153 | +// } | ||
154 | + | ||
155 | +// class LightSubscription<T> extends StreamSubscription<T> { | ||
156 | +// final RemoveSubscription<T> _removeSubscription; | ||
157 | +// LightSubscription(this._removeSubscription, | ||
158 | +// {this.onPause, this.onResume, this.onCancel}); | ||
159 | +// final void Function()? onPause; | ||
160 | +// final void Function()? onResume; | ||
161 | +// final FutureOr<void> Function()? onCancel; | ||
162 | + | ||
163 | +// bool? cancelOnError = false; | ||
164 | + | ||
165 | +// @override | ||
166 | +// Future<void> cancel() { | ||
167 | +// _removeSubscription(this); | ||
168 | +// onCancel?.call(); | ||
169 | +// return Future.value(); | ||
170 | +// } | ||
171 | + | ||
172 | +// OnData<T>? _data; | ||
173 | + | ||
174 | +// Function? _onError; | ||
175 | + | ||
176 | +// Callback? _onDone; | ||
177 | + | ||
178 | +// bool _isPaused = false; | ||
179 | + | ||
180 | +// @override | ||
181 | +// void onData(OnData<T>? handleData) => _data = handleData; | ||
182 | + | ||
183 | +// @override | ||
184 | +// void onError(Function? handleError) => _onError = handleError; | ||
185 | + | ||
186 | +// @override | ||
187 | +// void onDone(Callback? handleDone) => _onDone = handleDone; | ||
188 | + | ||
189 | +// @override | ||
190 | +// void pause([Future<void>? resumeSignal]) { | ||
191 | +// _isPaused = true; | ||
192 | +// onPause?.call(); | ||
193 | +// } | ||
194 | + | ||
195 | +// @override | ||
196 | +// void resume() { | ||
197 | +// _isPaused = false; | ||
198 | +// onResume?.call(); | ||
199 | +// } | ||
200 | + | ||
201 | +// @override | ||
202 | +// bool get isPaused => _isPaused; | ||
203 | + | ||
204 | +// @override | ||
205 | +// Future<E> asFuture<E>([E? futureValue]) => Future.value(futureValue); | ||
206 | +// } | ||
207 | + | ||
208 | +// class GetStreamTransformation<T> extends Stream<T> { | ||
209 | +// final AddSubscription<T> _addSubscription; | ||
210 | +// final RemoveSubscription<T> _removeSubscription; | ||
211 | +// GetStreamTransformation(this._addSubscription, this._removeSubscription); | ||
212 | + | ||
213 | +// @override | ||
214 | +// LightSubscription<T> listen(void Function(T event)? onData, | ||
215 | +// {Function? onError, void Function()? onDone, bool? cancelOnError}) { | ||
216 | +// final subs = LightSubscription<T>(_removeSubscription) | ||
217 | +// ..onData(onData) | ||
218 | +// ..onError(onError) | ||
219 | +// ..onDone(onDone); | ||
220 | +// _addSubscription(subs); | ||
221 | +// return subs; | ||
222 | +// } | ||
223 | +// } | ||
224 | + | ||
225 | +// typedef RemoveSubscription<T> = FutureOr<bool?> Function( | ||
226 | +// LightSubscription<T> subs); | ||
227 | + | ||
228 | +// typedef AddSubscription<T> = | ||
229 | +//FutureOr<void> Function(LightSubscription<T> subs); |
@@ -3,7 +3,6 @@ library rx_stream; | @@ -3,7 +3,6 @@ library rx_stream; | ||
3 | import 'dart:async'; | 3 | import 'dart:async'; |
4 | 4 | ||
5 | import '../rx_typedefs/rx_typedefs.dart'; | 5 | import '../rx_typedefs/rx_typedefs.dart'; |
6 | -import '../rx_types/rx_types.dart'; | ||
7 | 6 | ||
8 | -part 'get_stream.dart'; | 7 | +//part 'get_stream.dart'; |
9 | part 'mini_stream.dart'; | 8 | part 'mini_stream.dart'; |
@@ -4,7 +4,7 @@ part of rx_types; | @@ -4,7 +4,7 @@ part of rx_types; | ||
4 | /// reactivity | 4 | /// reactivity |
5 | /// of those `Widgets` and Rx values. | 5 | /// of those `Widgets` and Rx values. |
6 | 6 | ||
7 | -mixin RxObjectMixin<T> on NotifyManager<T> { | 7 | +mixin RxObjectMixin<T> on GetListenable<T> { |
8 | //late T _value; | 8 | //late T _value; |
9 | 9 | ||
10 | /// Makes a direct update of [value] adding it to the Stream | 10 | /// Makes a direct update of [value] adding it to the Stream |
@@ -25,9 +25,9 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | @@ -25,9 +25,9 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | ||
25 | /// person.refresh(); | 25 | /// person.refresh(); |
26 | /// print( person ); | 26 | /// print( person ); |
27 | /// ``` | 27 | /// ``` |
28 | - void refresh() { | ||
29 | - subject.add(value); | ||
30 | - } | 28 | + // void refresh() { |
29 | + // subject.add(value); | ||
30 | + // } | ||
31 | 31 | ||
32 | /// updates the value to `null` and adds it to the Stream. | 32 | /// updates the value to `null` and adds it to the Stream. |
33 | /// Even with null-safety coming, is still an important feature to support, as | 33 | /// Even with null-safety coming, is still an important feature to support, as |
@@ -59,6 +59,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | @@ -59,6 +59,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | ||
59 | /// onChanged: myText, | 59 | /// onChanged: myText, |
60 | /// ), | 60 | /// ), |
61 | ///``` | 61 | ///``` |
62 | + @override | ||
62 | T call([T? v]) { | 63 | T call([T? v]) { |
63 | if (v != null) { | 64 | if (v != null) { |
64 | value = v; | 65 | value = v; |
@@ -95,25 +96,18 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | @@ -95,25 +96,18 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | ||
95 | 96 | ||
96 | /// Updates the [value] and adds it to the stream, updating the observer | 97 | /// Updates the [value] and adds it to the stream, updating the observer |
97 | /// Widget, only if it's different from the previous value. | 98 | /// Widget, only if it's different from the previous value. |
99 | + @override | ||
98 | set value(T val) { | 100 | set value(T val) { |
99 | - if (subject.isClosed) return; | 101 | + if (isDisposed) return; |
100 | sentToStream = false; | 102 | sentToStream = false; |
101 | if (value == val && !firstRebuild) return; | 103 | if (value == val && !firstRebuild) return; |
102 | firstRebuild = false; | 104 | firstRebuild = false; |
103 | // _value = val; | 105 | // _value = val; |
104 | sentToStream = true; | 106 | sentToStream = true; |
105 | - subject.add(val); | 107 | + //TODO: Check this |
108 | + super.value = val; | ||
106 | } | 109 | } |
107 | 110 | ||
108 | - /// Returns the current [value] | ||
109 | - T get value { | ||
110 | - return subject.value; | ||
111 | - //RxInterface.proxy?.addListener(subject); | ||
112 | - // return _value; | ||
113 | - } | ||
114 | - | ||
115 | - Stream<T> get stream => subject.stream; | ||
116 | - | ||
117 | /// Returns a [StreamSubscription] similar to [listen], but with the | 111 | /// Returns a [StreamSubscription] similar to [listen], but with the |
118 | /// added benefit that it primes the stream with the current [value], rather | 112 | /// added benefit that it primes the stream with the current [value], rather |
119 | /// than waiting for the next [value]. This should not be called in [onInit] | 113 | /// than waiting for the next [value]. This should not be called in [onInit] |
@@ -127,6 +121,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | @@ -127,6 +121,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | ||
127 | cancelOnError: cancelOnError, | 121 | cancelOnError: cancelOnError, |
128 | ); | 122 | ); |
129 | 123 | ||
124 | + //TODO: Change to refresh???? | ||
130 | subject.add(value); | 125 | subject.add(value); |
131 | 126 | ||
132 | return subscription; | 127 | return subscription; |
@@ -137,64 +132,64 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | @@ -137,64 +132,64 @@ mixin RxObjectMixin<T> on NotifyManager<T> { | ||
137 | /// Closing the subscription will happen automatically when the observer | 132 | /// Closing the subscription will happen automatically when the observer |
138 | /// Widget (`GetX` or `Obx`) gets unmounted from the Widget tree. | 133 | /// Widget (`GetX` or `Obx`) gets unmounted from the Widget tree. |
139 | void bindStream(Stream<T> stream) { | 134 | void bindStream(Stream<T> stream) { |
140 | - final listSubscriptions = | ||
141 | - _subscriptions[subject] ??= <StreamSubscription>[]; | ||
142 | - listSubscriptions.add(stream.listen((va) => value = va)); | ||
143 | - } | ||
144 | -} | ||
145 | - | ||
146 | -class RxNotifier<T> = RxInterface<T> with NotifyManager<T>; | ||
147 | - | ||
148 | -mixin NotifyManager<T> { | ||
149 | - GetStream<T> subject = GetStream<T>(); | ||
150 | - final _subscriptions = <GetStream, List<StreamSubscription>>{}; | 135 | + // final listSubscriptions = |
136 | + // _subscriptions[subject] ??= <StreamSubscription>[]; | ||
151 | 137 | ||
152 | - bool get canUpdate => _subscriptions.isNotEmpty; | ||
153 | - | ||
154 | - /// This is an internal method. | ||
155 | - /// Subscribe to changes on the inner stream. | ||
156 | - void addListener(GetStream<T> rxGetx) { | ||
157 | - if (!_subscriptions.containsKey(rxGetx)) { | ||
158 | - final subs = rxGetx.listen((data) { | ||
159 | - if (!subject.isClosed) subject.add(data); | ||
160 | - }); | ||
161 | - final listSubscriptions = | ||
162 | - _subscriptions[rxGetx] ??= <StreamSubscription>[]; | ||
163 | - listSubscriptions.add(subs); | ||
164 | - } | ||
165 | - } | ||
166 | - | ||
167 | - StreamSubscription<T> listen( | ||
168 | - void Function(T) onData, { | ||
169 | - Function? onError, | ||
170 | - void Function()? onDone, | ||
171 | - bool? cancelOnError, | ||
172 | - }) => | ||
173 | - subject.listen( | ||
174 | - onData, | ||
175 | - onError: onError, | ||
176 | - onDone: onDone, | ||
177 | - cancelOnError: cancelOnError ?? false, | ||
178 | - ); | ||
179 | - | ||
180 | - /// Closes the subscriptions for this Rx, releasing the resources. | ||
181 | - void close() { | ||
182 | - _subscriptions.forEach((getStream, _subscriptions) { | ||
183 | - for (final subscription in _subscriptions) { | ||
184 | - subscription.cancel(); | ||
185 | - } | ||
186 | - }); | ||
187 | - | ||
188 | - _subscriptions.clear(); | ||
189 | - subject.close(); | 138 | + final sub = stream.listen((va) => value = va); |
139 | + reportAdd(sub.cancel); | ||
190 | } | 140 | } |
191 | } | 141 | } |
192 | 142 | ||
143 | +//class RxNotifier<T> = RxInterface<T> with NotifyManager<T>; | ||
144 | + | ||
145 | +// mixin NotifyManager<T> { | ||
146 | +// GetStream<T> subject = GetStream<T>(); | ||
147 | +// final _subscriptions = <GetStream, List<StreamSubscription>>{}; | ||
148 | + | ||
149 | +// bool get canUpdate => _subscriptions.isNotEmpty; | ||
150 | + | ||
151 | +// /// This is an internal method. | ||
152 | +// /// Subscribe to changes on the inner stream. | ||
153 | +// void addListener(GetStream<T> rxGetx) { | ||
154 | +// if (!_subscriptions.containsKey(rxGetx)) { | ||
155 | +// final subs = rxGetx.listen((data) { | ||
156 | +// if (!subject.isClosed) subject.add(data); | ||
157 | +// }); | ||
158 | +// final listSubscriptions = | ||
159 | +// _subscriptions[rxGetx] ??= <StreamSubscription>[]; | ||
160 | +// listSubscriptions.add(subs); | ||
161 | +// } | ||
162 | +// } | ||
163 | + | ||
164 | +// StreamSubscription<T> listen( | ||
165 | +// void Function(T) onData, { | ||
166 | +// Function? onError, | ||
167 | +// void Function()? onDone, | ||
168 | +// bool? cancelOnError, | ||
169 | +// }) => | ||
170 | +// subject.listen( | ||
171 | +// onData, | ||
172 | +// onError: onError, | ||
173 | +// onDone: onDone, | ||
174 | +// cancelOnError: cancelOnError ?? false, | ||
175 | +// ); | ||
176 | + | ||
177 | +// /// Closes the subscriptions for this Rx, releasing the resources. | ||
178 | +// void close() { | ||
179 | +// _subscriptions.forEach((getStream, _subscriptions) { | ||
180 | +// for (final subscription in _subscriptions) { | ||
181 | +// subscription.cancel(); | ||
182 | +// } | ||
183 | +// }); | ||
184 | + | ||
185 | +// _subscriptions.clear(); | ||
186 | +// subject.close(); | ||
187 | +// } | ||
188 | +// } | ||
189 | + | ||
193 | /// Base Rx class that manages all the stream logic for any Type. | 190 | /// Base Rx class that manages all the stream logic for any Type. |
194 | -abstract class _RxImpl<T> extends RxNotifier<T> with RxObjectMixin<T> { | ||
195 | - _RxImpl(T initial) { | ||
196 | - subject = GetStream.fromValue(initial); | ||
197 | - } | 191 | +abstract class _RxImpl<T> extends GetListenable<T> with RxObjectMixin<T> { |
192 | + _RxImpl(T initial) : super(initial); | ||
198 | 193 | ||
199 | void addError(Object error, [StackTrace? stackTrace]) { | 194 | void addError(Object error, [StackTrace? stackTrace]) { |
200 | subject.addError(error, stackTrace); | 195 | subject.addError(error, stackTrace); |
@@ -5,12 +5,10 @@ part of rx_types; | @@ -5,12 +5,10 @@ part of rx_types; | ||
5 | /// This interface is the contract that _RxImpl]<T> uses in all it's | 5 | /// This interface is the contract that _RxImpl]<T> uses in all it's |
6 | /// subclass. | 6 | /// subclass. |
7 | abstract class RxInterface<T> { | 7 | abstract class RxInterface<T> { |
8 | - static RxInterface? proxy; | ||
9 | - | ||
10 | - bool get canUpdate; | 8 | + //bool get canUpdate; |
11 | 9 | ||
12 | /// Adds a listener to stream | 10 | /// Adds a listener to stream |
13 | - void addListener(GetStream<T> rxGetx); | 11 | + void addListener(VoidCallback listener); |
14 | 12 | ||
15 | /// Close the Rx Variable | 13 | /// Close the Rx Variable |
16 | void close(); | 14 | void close(); |
@@ -20,13 +18,24 @@ abstract class RxInterface<T> { | @@ -20,13 +18,24 @@ abstract class RxInterface<T> { | ||
20 | {Function? onError, void Function()? onDone, bool? cancelOnError}); | 18 | {Function? onError, void Function()? onDone, bool? cancelOnError}); |
21 | 19 | ||
22 | /// Avoids an unsafe usage of the `proxy` | 20 | /// Avoids an unsafe usage of the `proxy` |
23 | - static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) { | ||
24 | - final _observer = RxInterface.proxy; | ||
25 | - RxInterface.proxy = observer; | ||
26 | - final result = builder(); | ||
27 | - if (!observer.canUpdate) { | ||
28 | - RxInterface.proxy = _observer; | ||
29 | - throw """ | 21 | + // static T notifyChildren<T>(RxNotifier observer, ValueGetter<T> builder) { |
22 | + // final _observer = RxInterface.proxy; | ||
23 | + // RxInterface.proxy = observer; | ||
24 | + // final result = builder(); | ||
25 | + // if (!observer.canUpdate) { | ||
26 | + // RxInterface.proxy = _observer; | ||
27 | + // throw ObxError(); | ||
28 | + // } | ||
29 | + // RxInterface.proxy = _observer; | ||
30 | + // return result; | ||
31 | + // } | ||
32 | +} | ||
33 | + | ||
34 | +class ObxError { | ||
35 | + const ObxError(); | ||
36 | + @override | ||
37 | + String toString() { | ||
38 | + return """ | ||
30 | [Get] the improper use of a GetX has been detected. | 39 | [Get] the improper use of a GetX has been detected. |
31 | You should only use GetX or Obx for the specific widget that will be updated. | 40 | You should only use GetX or Obx for the specific widget that will be updated. |
32 | If you are seeing this error, you probably did not insert any observable variables into GetX/Obx | 41 | If you are seeing this error, you probably did not insert any observable variables into GetX/Obx |
@@ -34,8 +43,5 @@ abstract class RxInterface<T> { | @@ -34,8 +43,5 @@ abstract class RxInterface<T> { | ||
34 | (example: GetX => HeavyWidget => variableObservable). | 43 | (example: GetX => HeavyWidget => variableObservable). |
35 | If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX. | 44 | If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX. |
36 | """; | 45 | """; |
37 | - } | ||
38 | - RxInterface.proxy = _observer; | ||
39 | - return result; | ||
40 | } | 46 | } |
41 | } | 47 | } |
1 | part of rx_types; | 1 | part of rx_types; |
2 | 2 | ||
3 | /// Create a list similar to `List<T>` | 3 | /// Create a list similar to `List<T>` |
4 | -class RxList<E> extends ListMixin<E> | ||
5 | - with NotifyManager<List<E>>, RxObjectMixin<List<E>> | ||
6 | - implements RxInterface<List<E>> { | ||
7 | - RxList([List<E> initial = const []]) { | ||
8 | - subject = GetStream.fromValue(List.from(initial)); | ||
9 | - } | 4 | +class RxList<E> extends GetListenable<List<E>> |
5 | + with ListMixin<E>, RxObjectMixin<List<E>> { | ||
6 | + RxList([List<E> initial = const []]) : super(initial); | ||
10 | 7 | ||
11 | factory RxList.filled(int length, E fill, {bool growable = false}) { | 8 | factory RxList.filled(int length, E fill, {bool growable = false}) { |
12 | return RxList(List.filled(length, fill, growable: growable)); | 9 | return RxList(List.filled(length, fill, growable: growable)); |
@@ -87,12 +84,12 @@ class RxList<E> extends ListMixin<E> | @@ -87,12 +84,12 @@ class RxList<E> extends ListMixin<E> | ||
87 | @override | 84 | @override |
88 | int get length => value.length; | 85 | int get length => value.length; |
89 | 86 | ||
90 | - @override | ||
91 | - @protected | ||
92 | - List<E> get value { | ||
93 | - RxInterface.proxy?.addListener(subject); | ||
94 | - return subject.value; | ||
95 | - } | 87 | + // @override |
88 | + // @protected | ||
89 | + // List<E> get value { | ||
90 | + // RxInterface.proxy?.addListener(subject); | ||
91 | + // return subject.value; | ||
92 | + // } | ||
96 | 93 | ||
97 | @override | 94 | @override |
98 | set length(int newLength) { | 95 | set length(int newLength) { |
1 | part of rx_types; | 1 | part of rx_types; |
2 | 2 | ||
3 | -class RxMap<K, V> extends MapMixin<K, V> | ||
4 | - with NotifyManager<Map<K, V>>, RxObjectMixin<Map<K, V>> | ||
5 | - implements RxInterface<Map<K, V>> { | ||
6 | - RxMap([Map<K, V> initial = const {}]) { | ||
7 | - subject = GetStream.fromValue(Map.from(initial)); | ||
8 | - } | 3 | +class RxMap<K, V> extends GetListenable<Map<K, V>> |
4 | + with MapMixin<K, V>, RxObjectMixin<Map<K, V>> { | ||
5 | + RxMap([Map<K, V> initial = const {}]) : super(initial); | ||
9 | 6 | ||
10 | factory RxMap.from(Map<K, V> other) { | 7 | factory RxMap.from(Map<K, V> other) { |
11 | return RxMap(Map.from(other)); | 8 | return RxMap(Map.from(other)); |
@@ -53,13 +50,13 @@ class RxMap<K, V> extends MapMixin<K, V> | @@ -53,13 +50,13 @@ class RxMap<K, V> extends MapMixin<K, V> | ||
53 | return val; | 50 | return val; |
54 | } | 51 | } |
55 | 52 | ||
56 | - @override | ||
57 | - @protected | ||
58 | - Map<K, V> get value { | ||
59 | - return subject.value; | ||
60 | - // RxInterface.proxy?.addListener(subject); | ||
61 | - // return _value; | ||
62 | - } | 53 | + // @override |
54 | + // @protected | ||
55 | + // Map<K, V> get value { | ||
56 | + // return subject.value; | ||
57 | + // // RxInterface.proxy?.addListener(subject); | ||
58 | + // // return _value; | ||
59 | + // } | ||
63 | } | 60 | } |
64 | 61 | ||
65 | extension MapExtension<K, V> on Map<K, V> { | 62 | extension MapExtension<K, V> on Map<K, V> { |
@@ -99,6 +96,7 @@ extension MapExtension<K, V> on Map<K, V> { | @@ -99,6 +96,7 @@ extension MapExtension<K, V> on Map<K, V> { | ||
99 | final map = (this as RxMap); | 96 | final map = (this as RxMap); |
100 | if (map.value == val) return; | 97 | if (map.value == val) return; |
101 | map.value = val; | 98 | map.value = val; |
99 | + // ignore: invalid_use_of_protected_member | ||
102 | map.refresh(); | 100 | map.refresh(); |
103 | } else { | 101 | } else { |
104 | if (this == val) return; | 102 | if (this == val) return; |
1 | part of rx_types; | 1 | part of rx_types; |
2 | 2 | ||
3 | -class RxSet<E> extends SetMixin<E> | ||
4 | - with NotifyManager<Set<E>>, RxObjectMixin<Set<E>> | ||
5 | - implements RxInterface<Set<E>> { | ||
6 | - RxSet([Set<E> initial = const {}]) { | ||
7 | - subject = GetStream.fromValue(Set.from(initial)); | ||
8 | - } | 3 | +class RxSet<E> extends GetListenable<Set<E>> |
4 | + with SetMixin<E>, RxObjectMixin<Set<E>> { | ||
5 | + RxSet([Set<E> initial = const {}]) : super(initial); | ||
9 | 6 | ||
10 | /// Special override to push() element(s) in a reactive way | 7 | /// Special override to push() element(s) in a reactive way |
11 | /// inside the List, | 8 | /// inside the List, |
@@ -20,13 +17,13 @@ class RxSet<E> extends SetMixin<E> | @@ -20,13 +17,13 @@ class RxSet<E> extends SetMixin<E> | ||
20 | refresh(); | 17 | refresh(); |
21 | } | 18 | } |
22 | 19 | ||
23 | - @override | ||
24 | - @protected | ||
25 | - Set<E> get value { | ||
26 | - return subject.value; | ||
27 | - // RxInterface.proxy?.addListener(subject); | ||
28 | - // return _value; | ||
29 | - } | 20 | + // @override |
21 | + // @protected | ||
22 | + // Set<E> get value { | ||
23 | + // return subject.value; | ||
24 | + // // RxInterface.proxy?.addListener(subject); | ||
25 | + // // return _value; | ||
26 | + // } | ||
30 | 27 | ||
31 | @override | 28 | @override |
32 | @protected | 29 | @protected |
@@ -5,7 +5,7 @@ import 'dart:collection'; | @@ -5,7 +5,7 @@ import 'dart:collection'; | ||
5 | 5 | ||
6 | import 'package:flutter/foundation.dart'; | 6 | import 'package:flutter/foundation.dart'; |
7 | 7 | ||
8 | -import '../rx_stream/rx_stream.dart'; | 8 | +import '../../../get_state_manager/src/rx_flutter/rx_notifier.dart'; |
9 | import '../rx_typedefs/rx_typedefs.dart'; | 9 | import '../rx_typedefs/rx_typedefs.dart'; |
10 | 10 | ||
11 | part 'rx_core/rx_impl.dart'; | 11 | part 'rx_core/rx_impl.dart'; |
1 | import 'dart:async'; | 1 | import 'dart:async'; |
2 | 2 | ||
3 | import '../../../get_core/get_core.dart'; | 3 | import '../../../get_core/get_core.dart'; |
4 | +import '../../../get_state_manager/src/rx_flutter/rx_notifier.dart'; | ||
4 | import '../rx_types/rx_types.dart'; | 5 | import '../rx_types/rx_types.dart'; |
5 | import 'utils/debouncer.dart'; | 6 | import 'utils/debouncer.dart'; |
6 | 7 | ||
@@ -57,7 +58,7 @@ class Workers { | @@ -57,7 +58,7 @@ class Workers { | ||
57 | /// } | 58 | /// } |
58 | /// ``` | 59 | /// ``` |
59 | Worker ever<T>( | 60 | Worker ever<T>( |
60 | - RxInterface<T> listener, | 61 | + GetListenable<T> listener, |
61 | WorkerCallback<T> callback, { | 62 | WorkerCallback<T> callback, { |
62 | dynamic condition = true, | 63 | dynamic condition = true, |
63 | Function? onError, | 64 | Function? onError, |
@@ -132,7 +133,7 @@ Worker everAll( | @@ -132,7 +133,7 @@ Worker everAll( | ||
132 | /// } | 133 | /// } |
133 | ///``` | 134 | ///``` |
134 | Worker once<T>( | 135 | Worker once<T>( |
135 | - RxInterface<T> listener, | 136 | + GetListenable<T> listener, |
136 | WorkerCallback<T> callback, { | 137 | WorkerCallback<T> callback, { |
137 | dynamic condition = true, | 138 | dynamic condition = true, |
138 | Function? onError, | 139 | Function? onError, |
@@ -175,7 +176,7 @@ Worker once<T>( | @@ -175,7 +176,7 @@ Worker once<T>( | ||
175 | /// ); | 176 | /// ); |
176 | /// ``` | 177 | /// ``` |
177 | Worker interval<T>( | 178 | Worker interval<T>( |
178 | - RxInterface<T> listener, | 179 | + GetListenable<T> listener, |
179 | WorkerCallback<T> callback, { | 180 | WorkerCallback<T> callback, { |
180 | Duration time = const Duration(seconds: 1), | 181 | Duration time = const Duration(seconds: 1), |
181 | dynamic condition = true, | 182 | dynamic condition = true, |
@@ -219,7 +220,7 @@ Worker interval<T>( | @@ -219,7 +220,7 @@ Worker interval<T>( | ||
219 | /// } | 220 | /// } |
220 | /// ``` | 221 | /// ``` |
221 | Worker debounce<T>( | 222 | Worker debounce<T>( |
222 | - RxInterface<T> listener, | 223 | + GetListenable<T> listener, |
223 | WorkerCallback<T> callback, { | 224 | WorkerCallback<T> callback, { |
224 | Duration? time, | 225 | Duration? time, |
225 | Function? onError, | 226 | Function? onError, |
1 | -import 'dart:async'; | ||
2 | - | ||
3 | import 'package:flutter/foundation.dart'; | 1 | import 'package:flutter/foundation.dart'; |
4 | import 'package:flutter/widgets.dart'; | 2 | import 'package:flutter/widgets.dart'; |
5 | 3 | ||
6 | import '../../../get_core/get_core.dart'; | 4 | import '../../../get_core/get_core.dart'; |
7 | import '../../../get_instance/src/get_instance.dart'; | 5 | import '../../../get_instance/src/get_instance.dart'; |
8 | import '../../../get_instance/src/lifecycle.dart'; | 6 | import '../../../get_instance/src/lifecycle.dart'; |
9 | -import '../../../get_rx/src/rx_types/rx_types.dart'; | 7 | +import '../simple/list_notifier.dart'; |
8 | +import '../simple/simple_builder.dart'; | ||
10 | 9 | ||
11 | typedef GetXControllerBuilder<T extends GetLifeCycleMixin> = Widget Function( | 10 | typedef GetXControllerBuilder<T extends GetLifeCycleMixin> = Widget Function( |
12 | T controller); | 11 | T controller); |
13 | 12 | ||
13 | +class StatefulObserverComponent = StatefulElement with ObserverComponent; | ||
14 | + | ||
14 | class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { | 15 | class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { |
15 | final GetXControllerBuilder<T> builder; | 16 | final GetXControllerBuilder<T> builder; |
16 | final bool global; | 17 | final bool global; |
@@ -39,6 +40,9 @@ class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { | @@ -39,6 +40,9 @@ class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { | ||
39 | }); | 40 | }); |
40 | 41 | ||
41 | @override | 42 | @override |
43 | + StatefulElement createElement() => StatefulElement(this); | ||
44 | + | ||
45 | + @override | ||
42 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { | 46 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
43 | super.debugFillProperties(properties); | 47 | super.debugFillProperties(properties); |
44 | properties | 48 | properties |
@@ -55,10 +59,8 @@ class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { | @@ -55,10 +59,8 @@ class GetX<T extends GetLifeCycleMixin> extends StatefulWidget { | ||
55 | } | 59 | } |
56 | 60 | ||
57 | class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { | 61 | class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { |
58 | - final _observer = RxNotifier(); | ||
59 | T? controller; | 62 | T? controller; |
60 | bool? _isCreator = false; | 63 | bool? _isCreator = false; |
61 | - late StreamSubscription _subs; | ||
62 | 64 | ||
63 | @override | 65 | @override |
64 | void initState() { | 66 | void initState() { |
@@ -83,7 +85,7 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { | @@ -83,7 +85,7 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { | ||
83 | if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) { | 85 | if (widget.global && Get.smartManagement == SmartManagement.onlyBuilder) { |
84 | controller?.onStart(); | 86 | controller?.onStart(); |
85 | } | 87 | } |
86 | - _subs = _observer.listen((data) => setState(() {}), cancelOnError: false); | 88 | + |
87 | super.initState(); | 89 | super.initState(); |
88 | } | 90 | } |
89 | 91 | ||
@@ -109,22 +111,29 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { | @@ -109,22 +111,29 @@ class GetXState<T extends GetLifeCycleMixin> extends State<GetX<T>> { | ||
109 | GetInstance().delete<T>(tag: widget.tag); | 111 | GetInstance().delete<T>(tag: widget.tag); |
110 | } | 112 | } |
111 | } | 113 | } |
112 | - _subs.cancel(); | ||
113 | - _observer.close(); | 114 | + |
115 | + for (final disposer in disposers) { | ||
116 | + disposer(); | ||
117 | + } | ||
118 | + | ||
114 | controller = null; | 119 | controller = null; |
115 | _isCreator = null; | 120 | _isCreator = null; |
116 | super.dispose(); | 121 | super.dispose(); |
117 | } | 122 | } |
118 | 123 | ||
124 | + void _update() { | ||
125 | + setState(() {}); | ||
126 | + } | ||
127 | + | ||
128 | + final disposers = <Disposer>[]; | ||
129 | + | ||
130 | + @override | ||
131 | + Widget build(BuildContext context) => TaskManager.instance | ||
132 | + .exchange(disposers, _update, () => widget.builder(controller!)); | ||
133 | + | ||
119 | @override | 134 | @override |
120 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { | 135 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
121 | super.debugFillProperties(properties); | 136 | super.debugFillProperties(properties); |
122 | properties.add(DiagnosticsProperty<T>('controller', controller)); | 137 | properties.add(DiagnosticsProperty<T>('controller', controller)); |
123 | } | 138 | } |
124 | - | ||
125 | - @override | ||
126 | - Widget build(BuildContext context) => RxInterface.notifyChildren( | ||
127 | - _observer, | ||
128 | - () => widget.builder(controller!), | ||
129 | - ); | ||
130 | } | 139 | } |
1 | +import 'dart:async'; | ||
2 | + | ||
1 | import 'package:flutter/foundation.dart'; | 3 | import 'package:flutter/foundation.dart'; |
2 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
3 | 5 | ||
@@ -5,37 +7,52 @@ import '../../../instance_manager.dart'; | @@ -5,37 +7,52 @@ import '../../../instance_manager.dart'; | ||
5 | import '../../get_state_manager.dart'; | 7 | import '../../get_state_manager.dart'; |
6 | import '../simple/list_notifier.dart'; | 8 | import '../simple/list_notifier.dart'; |
7 | 9 | ||
8 | -mixin StateMixin<T> on ListNotifierMixin { | ||
9 | - late T _value; | ||
10 | - RxStatus? _status; | ||
11 | - | ||
12 | - bool _isNullOrEmpty(dynamic val) { | ||
13 | - if (val == null) return true; | 10 | +extension _Empty on Object { |
11 | + bool _isEmpty() { | ||
12 | + final val = this; | ||
13 | + // if (val == null) return true; | ||
14 | var result = false; | 14 | var result = false; |
15 | if (val is Iterable) { | 15 | if (val is Iterable) { |
16 | result = val.isEmpty; | 16 | result = val.isEmpty; |
17 | } else if (val is String) { | 17 | } else if (val is String) { |
18 | - result = val.isEmpty; | 18 | + result = val.trim().isEmpty; |
19 | } else if (val is Map) { | 19 | } else if (val is Map) { |
20 | result = val.isEmpty; | 20 | result = val.isEmpty; |
21 | } | 21 | } |
22 | return result; | 22 | return result; |
23 | } | 23 | } |
24 | +} | ||
24 | 25 | ||
25 | - void _fillEmptyStatus() { | ||
26 | - _status = _isNullOrEmpty(_value) ? RxStatus.loading() : RxStatus.success(); | 26 | +mixin StateMixin<T> on ListNotifier { |
27 | + late T _value; | ||
28 | + GetState<T>? _status; | ||
29 | + | ||
30 | + void _fillInitialStatus() { | ||
31 | + _status = (value == null || value!._isEmpty()) | ||
32 | + ? GetState<T>.loading() | ||
33 | + : GetState<T>.success(_value); | ||
27 | } | 34 | } |
28 | 35 | ||
29 | - RxStatus get status { | ||
30 | - notifyChildrens(); | ||
31 | - return _status ??= _status = RxStatus.loading(); | 36 | + GetState<T> get status { |
37 | + reportRead(); | ||
38 | + return _status ??= _status = GetState.loading(); | ||
32 | } | 39 | } |
33 | 40 | ||
34 | T get state => value; | 41 | T get state => value; |
35 | 42 | ||
43 | + set status(GetState<T> newStatus) { | ||
44 | + if (newStatus == status) return; | ||
45 | + _status = newStatus; | ||
46 | + if (newStatus is SuccessState<T>) { | ||
47 | + _value = newStatus.data!; | ||
48 | + return; | ||
49 | + } | ||
50 | + refresh(); | ||
51 | + } | ||
52 | + | ||
36 | @protected | 53 | @protected |
37 | T get value { | 54 | T get value { |
38 | - notifyChildrens(); | 55 | + reportRead(); |
39 | return _value; | 56 | return _value; |
40 | } | 57 | } |
41 | 58 | ||
@@ -46,43 +63,103 @@ mixin StateMixin<T> on ListNotifierMixin { | @@ -46,43 +63,103 @@ mixin StateMixin<T> on ListNotifierMixin { | ||
46 | refresh(); | 63 | refresh(); |
47 | } | 64 | } |
48 | 65 | ||
49 | - @protected | ||
50 | - void change(T newState, {RxStatus? status}) { | ||
51 | - var _canUpdate = false; | ||
52 | - if (status != null) { | ||
53 | - _status = status; | ||
54 | - _canUpdate = true; | ||
55 | - } | ||
56 | - if (newState != _value) { | ||
57 | - _value = newState; | ||
58 | - _canUpdate = true; | ||
59 | - } | ||
60 | - if (_canUpdate) { | ||
61 | - refresh(); | ||
62 | - } | ||
63 | - } | ||
64 | - | ||
65 | - void append(Future<T> Function() body(), {String? errorMessage}) { | 66 | + void futurize(Future<T> Function() body(), |
67 | + {String? errorMessage, bool useEmpty = true}) { | ||
66 | final compute = body(); | 68 | final compute = body(); |
67 | compute().then((newValue) { | 69 | compute().then((newValue) { |
68 | - change(newValue, status: RxStatus.success()); | 70 | + if ((newValue == null || newValue._isEmpty()) && useEmpty) { |
71 | + status = GetState<T>.loading(); | ||
72 | + } else { | ||
73 | + status = GetState<T>.success(newValue); | ||
74 | + } | ||
69 | }, onError: (err) { | 75 | }, onError: (err) { |
70 | - change(state, status: RxStatus.error(errorMessage ?? err.toString())); | 76 | + status = GetState.error(errorMessage ?? err.toString()); |
71 | }); | 77 | }); |
72 | } | 78 | } |
73 | } | 79 | } |
74 | 80 | ||
81 | +class GetListenable<T> extends ListNotifierSingle | ||
82 | + implements ValueListenable<T> { | ||
83 | + GetListenable(T val) : _value = val; | ||
84 | + | ||
85 | + StreamController<T>? _controller; | ||
86 | + | ||
87 | + StreamController<T> get subject { | ||
88 | + if (_controller == null) { | ||
89 | + _controller = StreamController<T>.broadcast(); | ||
90 | + addListener(_streamListener); | ||
91 | + } | ||
92 | + return _controller!; | ||
93 | + } | ||
94 | + | ||
95 | + void _streamListener() { | ||
96 | + _controller?.add(_value); | ||
97 | + } | ||
98 | + | ||
99 | + @mustCallSuper | ||
100 | + void close() { | ||
101 | + removeListener(_streamListener); | ||
102 | + _controller?.close(); | ||
103 | + dispose(); | ||
104 | + } | ||
105 | + | ||
106 | + Stream<T> get stream { | ||
107 | + return subject.stream; | ||
108 | + } | ||
109 | + | ||
110 | + T _value; | ||
111 | + | ||
112 | + @override | ||
113 | + T get value { | ||
114 | + reportRead(); | ||
115 | + return _value; | ||
116 | + } | ||
117 | + | ||
118 | + void _notify() { | ||
119 | + refresh(); | ||
120 | + } | ||
121 | + | ||
122 | + set value(T newValue) { | ||
123 | + if (_value == newValue) return; | ||
124 | + _value = newValue; | ||
125 | + _notify(); | ||
126 | + } | ||
127 | + | ||
128 | + T? call([T? v]) { | ||
129 | + if (v != null) { | ||
130 | + value = v; | ||
131 | + } | ||
132 | + return value; | ||
133 | + } | ||
134 | + | ||
135 | + StreamSubscription<T> listen( | ||
136 | + void Function(T)? onData, { | ||
137 | + Function? onError, | ||
138 | + void Function()? onDone, | ||
139 | + bool? cancelOnError, | ||
140 | + }) => | ||
141 | + stream.listen( | ||
142 | + onData, | ||
143 | + onError: onError, | ||
144 | + onDone: onDone, | ||
145 | + cancelOnError: cancelOnError ?? false, | ||
146 | + ); | ||
147 | + | ||
148 | + @override | ||
149 | + String toString() => value.toString(); | ||
150 | +} | ||
151 | + | ||
75 | class Value<T> extends ListNotifier | 152 | class Value<T> extends ListNotifier |
76 | with StateMixin<T> | 153 | with StateMixin<T> |
77 | implements ValueListenable<T?> { | 154 | implements ValueListenable<T?> { |
78 | Value(T val) { | 155 | Value(T val) { |
79 | _value = val; | 156 | _value = val; |
80 | - _fillEmptyStatus(); | 157 | + _fillInitialStatus(); |
81 | } | 158 | } |
82 | 159 | ||
83 | @override | 160 | @override |
84 | T get value { | 161 | T get value { |
85 | - notifyChildrens(); | 162 | + reportRead(); |
86 | return _value; | 163 | return _value; |
87 | } | 164 | } |
88 | 165 | ||
@@ -111,12 +188,6 @@ class Value<T> extends ListNotifier | @@ -111,12 +188,6 @@ class Value<T> extends ListNotifier | ||
111 | dynamic toJson() => (value as dynamic)?.toJson(); | 188 | dynamic toJson() => (value as dynamic)?.toJson(); |
112 | } | 189 | } |
113 | 190 | ||
114 | -extension ReactiveT<T> on T { | ||
115 | - Value<T> get reactive => Value<T>(this); | ||
116 | -} | ||
117 | - | ||
118 | -typedef Condition = bool Function(); | ||
119 | - | ||
120 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin { | 191 | abstract class GetNotifier<T> extends Value<T> with GetLifeCycleMixin { |
121 | GetNotifier(T initial) : super(initial); | 192 | GetNotifier(T initial) : super(initial); |
122 | } | 193 | } |
@@ -128,7 +199,7 @@ extension StateExt<T> on StateMixin<T> { | @@ -128,7 +199,7 @@ extension StateExt<T> on StateMixin<T> { | ||
128 | Widget? onLoading, | 199 | Widget? onLoading, |
129 | Widget? onEmpty, | 200 | Widget? onEmpty, |
130 | }) { | 201 | }) { |
131 | - return SimpleBuilder(builder: (_) { | 202 | + return Observer(builder: (_) { |
132 | if (status.isLoading) { | 203 | if (status.isLoading) { |
133 | return onLoading ?? const Center(child: CircularProgressIndicator()); | 204 | return onLoading ?? const Center(child: CircularProgressIndicator()); |
134 | } else if (status.isError) { | 205 | } else if (status.isError) { |
@@ -145,78 +216,40 @@ extension StateExt<T> on StateMixin<T> { | @@ -145,78 +216,40 @@ extension StateExt<T> on StateMixin<T> { | ||
145 | } | 216 | } |
146 | } | 217 | } |
147 | 218 | ||
148 | -class RxStatus { | ||
149 | - final bool isLoading; | ||
150 | - final bool isError; | ||
151 | - final bool isSuccess; | ||
152 | - final bool isEmpty; | ||
153 | - final bool isLoadingMore; | ||
154 | - final String? errorMessage; | ||
155 | - | ||
156 | - RxStatus._({ | ||
157 | - this.isEmpty = false, | ||
158 | - this.isLoading = false, | ||
159 | - this.isError = false, | ||
160 | - this.isSuccess = false, | ||
161 | - this.errorMessage, | ||
162 | - this.isLoadingMore = false, | ||
163 | - }); | ||
164 | - | ||
165 | - factory RxStatus.loading() { | ||
166 | - return RxStatus._(isLoading: true); | ||
167 | - } | ||
168 | - | ||
169 | - factory RxStatus.loadingMore() { | ||
170 | - return RxStatus._(isSuccess: true, isLoadingMore: true); | ||
171 | - } | ||
172 | - | ||
173 | - factory RxStatus.success() { | ||
174 | - return RxStatus._(isSuccess: true); | ||
175 | - } | ||
176 | - | ||
177 | - factory RxStatus.error([String? message]) { | ||
178 | - return RxStatus._(isError: true, errorMessage: message); | ||
179 | - } | ||
180 | - | ||
181 | - factory RxStatus.empty() { | ||
182 | - return RxStatus._(isEmpty: true); | ||
183 | - } | ||
184 | -} | ||
185 | - | ||
186 | typedef NotifierBuilder<T> = Widget Function(T state); | 219 | typedef NotifierBuilder<T> = Widget Function(T state); |
187 | 220 | ||
188 | -abstract class GState<T> { | ||
189 | - const GState(); | ||
190 | - factory GState.loading() => GLoading(); | ||
191 | - factory GState.error(String message) => GError(message); | ||
192 | - factory GState.empty() => GEmpty(); | ||
193 | - factory GState.success(T data) => GSuccess(data); | 221 | +abstract class GetState<T> { |
222 | + const GetState(); | ||
223 | + factory GetState.loading() => LoadingState(); | ||
224 | + factory GetState.error(String message) => ErrorState(message); | ||
225 | + factory GetState.empty() => EmptyState(); | ||
226 | + factory GetState.success(T data) => SuccessState(data); | ||
194 | } | 227 | } |
195 | 228 | ||
196 | -class GLoading<T> extends GState<T> {} | 229 | +class LoadingState<T> extends GetState<T> {} |
197 | 230 | ||
198 | -class GSuccess<T> extends GState<T> { | 231 | +class SuccessState<T> extends GetState<T> { |
199 | final T data; | 232 | final T data; |
200 | 233 | ||
201 | - GSuccess(this.data); | 234 | + SuccessState(this.data); |
202 | } | 235 | } |
203 | 236 | ||
204 | -class GError<T, S> extends GState<T> { | 237 | +class ErrorState<T, S> extends GetState<T> { |
205 | final S? error; | 238 | final S? error; |
206 | - GError([this.error]); | 239 | + ErrorState([this.error]); |
207 | } | 240 | } |
208 | 241 | ||
209 | -class GEmpty<T> extends GState<T> {} | 242 | +class EmptyState<T> extends GetState<T> {} |
210 | 243 | ||
211 | -extension StatusDataExt<T> on GState<T> { | ||
212 | - bool get isLoading => this is GLoading; | ||
213 | - bool get isSuccess => this is GSuccess; | ||
214 | - bool get isError => this is GError; | ||
215 | - bool get isEmpty => this is GEmpty; | 244 | +extension StatusDataExt<T> on GetState<T> { |
245 | + bool get isLoading => this is LoadingState; | ||
246 | + bool get isSuccess => this is SuccessState; | ||
247 | + bool get isError => this is ErrorState; | ||
248 | + bool get isEmpty => this is EmptyState; | ||
216 | String get errorMessage { | 249 | String get errorMessage { |
217 | - final isError = this is GError; | 250 | + final isError = this is ErrorState; |
218 | if (isError) { | 251 | if (isError) { |
219 | - final err = this as GError; | 252 | + final err = this as ErrorState; |
220 | if (err.error != null && err.error is String) { | 253 | if (err.error != null && err.error is String) { |
221 | return err.error as String; | 254 | return err.error as String; |
222 | } | 255 | } |
@@ -224,4 +257,12 @@ extension StatusDataExt<T> on GState<T> { | @@ -224,4 +257,12 @@ extension StatusDataExt<T> on GState<T> { | ||
224 | 257 | ||
225 | return ''; | 258 | return ''; |
226 | } | 259 | } |
260 | + | ||
261 | + T? get data { | ||
262 | + if (this is SuccessState<T>) { | ||
263 | + final success = this as SuccessState<T>; | ||
264 | + return success.data; | ||
265 | + } | ||
266 | + return null; | ||
267 | + } | ||
227 | } | 268 | } |
1 | -import 'dart:async'; | ||
2 | - | ||
3 | -import 'package:flutter/foundation.dart'; | ||
4 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; |
5 | 2 | ||
6 | import '../../../get_rx/src/rx_types/rx_types.dart'; | 3 | import '../../../get_rx/src/rx_types/rx_types.dart'; |
4 | +import '../simple/simple_builder.dart'; | ||
7 | 5 | ||
8 | typedef WidgetCallback = Widget Function(); | 6 | typedef WidgetCallback = Widget Function(); |
9 | 7 | ||
@@ -12,48 +10,8 @@ typedef WidgetCallback = Widget Function(); | @@ -12,48 +10,8 @@ typedef WidgetCallback = Widget Function(); | ||
12 | /// See also: | 10 | /// See also: |
13 | /// - [Obx] | 11 | /// - [Obx] |
14 | /// - [ObxValue] | 12 | /// - [ObxValue] |
15 | -abstract class ObxWidget extends StatefulWidget { | 13 | +abstract class ObxWidget extends ObxStatelessWidget { |
16 | const ObxWidget({Key? key}) : super(key: key); | 14 | const ObxWidget({Key? key}) : super(key: key); |
17 | - | ||
18 | - @override | ||
19 | - void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||
20 | - super.debugFillProperties(properties); | ||
21 | - properties..add(ObjectFlagProperty<Function>.has('builder', build)); | ||
22 | - } | ||
23 | - | ||
24 | - @override | ||
25 | - _ObxState createState() => _ObxState(); | ||
26 | - | ||
27 | - @protected | ||
28 | - Widget build(); | ||
29 | -} | ||
30 | - | ||
31 | -class _ObxState extends State<ObxWidget> { | ||
32 | - final _observer = RxNotifier(); | ||
33 | - late StreamSubscription subs; | ||
34 | - | ||
35 | - @override | ||
36 | - void initState() { | ||
37 | - super.initState(); | ||
38 | - subs = _observer.subject.stream.listen(_updateTree, cancelOnError: false); | ||
39 | - } | ||
40 | - | ||
41 | - void _updateTree(_) { | ||
42 | - if (mounted) { | ||
43 | - setState(() {}); | ||
44 | - } | ||
45 | - } | ||
46 | - | ||
47 | - @override | ||
48 | - void dispose() { | ||
49 | - subs.cancel(); | ||
50 | - _observer.close(); | ||
51 | - super.dispose(); | ||
52 | - } | ||
53 | - | ||
54 | - @override | ||
55 | - Widget build(BuildContext context) => | ||
56 | - RxInterface.notifyChildren(_observer, widget.build); | ||
57 | } | 15 | } |
58 | 16 | ||
59 | /// The simplest reactive widget in GetX. | 17 | /// The simplest reactive widget in GetX. |
@@ -69,7 +27,9 @@ class Obx extends ObxWidget { | @@ -69,7 +27,9 @@ class Obx extends ObxWidget { | ||
69 | const Obx(this.builder); | 27 | const Obx(this.builder); |
70 | 28 | ||
71 | @override | 29 | @override |
72 | - Widget build() => builder(); | 30 | + Widget build(BuildContext context) { |
31 | + return builder(); | ||
32 | + } | ||
73 | } | 33 | } |
74 | 34 | ||
75 | /// Similar to Obx, but manages a local state. | 35 | /// Similar to Obx, but manages a local state. |
@@ -90,5 +50,5 @@ class ObxValue<T extends RxInterface> extends ObxWidget { | @@ -90,5 +50,5 @@ class ObxValue<T extends RxInterface> extends ObxWidget { | ||
90 | const ObxValue(this.builder, this.data, {Key? key}) : super(key: key); | 50 | const ObxValue(this.builder, this.data, {Key? key}) : super(key: key); |
91 | 51 | ||
92 | @override | 52 | @override |
93 | - Widget build() => builder(data); | 53 | + Widget build(BuildContext context) => builder(data); |
94 | } | 54 | } |
@@ -6,8 +6,7 @@ import '../rx_flutter/rx_notifier.dart'; | @@ -6,8 +6,7 @@ import '../rx_flutter/rx_notifier.dart'; | ||
6 | import 'list_notifier.dart'; | 6 | import 'list_notifier.dart'; |
7 | 7 | ||
8 | // ignore: prefer_mixin | 8 | // ignore: prefer_mixin |
9 | -abstract class GetxController extends Listenable | ||
10 | - with GetLifeCycleMixin, ListNotifierMixin { | 9 | +abstract class GetxController extends ListNotifier with GetLifeCycleMixin { |
11 | /// Rebuilds `GetBuilder` each time you call `update()`; | 10 | /// Rebuilds `GetBuilder` each time you call `update()`; |
12 | /// Can take a List of [ids], that will only update the matching | 11 | /// Can take a List of [ids], that will only update the matching |
13 | /// `GetBuilder( id: )`, | 12 | /// `GetBuilder( id: )`, |
@@ -73,6 +72,8 @@ mixin ScrollMixin on GetLifeCycleMixin { | @@ -73,6 +72,8 @@ mixin ScrollMixin on GetLifeCycleMixin { | ||
73 | 72 | ||
74 | abstract class RxController with GetLifeCycleMixin {} | 73 | abstract class RxController with GetLifeCycleMixin {} |
75 | 74 | ||
75 | +abstract class StateController<T> extends GetxController with StateMixin<T> {} | ||
76 | + | ||
76 | abstract class SuperController<T> extends FullLifeCycleController | 77 | abstract class SuperController<T> extends FullLifeCycleController |
77 | with FullLifeCycleMixin, StateMixin<T> {} | 78 | with FullLifeCycleMixin, StateMixin<T> {} |
78 | 79 |
1 | import 'dart:collection'; | 1 | import 'dart:collection'; |
2 | 2 | ||
3 | -import 'package:flutter/widgets.dart'; | 3 | +import 'package:flutter/foundation.dart'; |
4 | 4 | ||
5 | // This callback remove the listener on addListener function | 5 | // This callback remove the listener on addListener function |
6 | typedef Disposer = void Function(); | 6 | typedef Disposer = void Function(); |
@@ -9,45 +9,60 @@ typedef Disposer = void Function(); | @@ -9,45 +9,60 @@ typedef Disposer = void Function(); | ||
9 | // if it brings overhead the extra call, | 9 | // if it brings overhead the extra call, |
10 | typedef GetStateUpdate = void Function(); | 10 | typedef GetStateUpdate = void Function(); |
11 | 11 | ||
12 | -class ListNotifier extends Listenable with ListNotifierMixin {} | 12 | +class ListNotifier extends Listenable |
13 | + with ListNotifierSingleMixin, ListNotifierGroupMixin {} | ||
13 | 14 | ||
14 | -mixin ListNotifierMixin on Listenable { | 15 | +class ListNotifierSingle = ListNotifier with ListNotifierSingleMixin; |
16 | + | ||
17 | +class ListNotifierGroup = ListNotifier with ListNotifierGroupMixin; | ||
18 | + | ||
19 | +mixin ListNotifierSingleMixin on Listenable { | ||
15 | List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[]; | 20 | List<GetStateUpdate?>? _updaters = <GetStateUpdate?>[]; |
16 | 21 | ||
17 | - HashMap<Object?, List<GetStateUpdate>>? _updatersGroupIds = | ||
18 | - HashMap<Object?, List<GetStateUpdate>>(); | 22 | + @override |
23 | + Disposer addListener(GetStateUpdate listener) { | ||
24 | + assert(_debugAssertNotDisposed()); | ||
25 | + _updaters!.add(listener); | ||
26 | + return () => _updaters!.remove(listener); | ||
27 | + } | ||
28 | + | ||
29 | + bool containsListener(GetStateUpdate listener) { | ||
30 | + return _updaters?.contains(listener) ?? false; | ||
31 | + } | ||
32 | + | ||
33 | + @override | ||
34 | + void removeListener(VoidCallback listener) { | ||
35 | + assert(_debugAssertNotDisposed()); | ||
36 | + _updaters!.remove(listener); | ||
37 | + } | ||
19 | 38 | ||
20 | @protected | 39 | @protected |
21 | void refresh() { | 40 | void refresh() { |
22 | assert(_debugAssertNotDisposed()); | 41 | assert(_debugAssertNotDisposed()); |
23 | - | ||
24 | _notifyUpdate(); | 42 | _notifyUpdate(); |
25 | } | 43 | } |
26 | 44 | ||
45 | + @protected | ||
46 | + void reportRead() { | ||
47 | + TaskManager.instance.notify(this); | ||
48 | + } | ||
49 | + | ||
50 | + @protected | ||
51 | + void reportAdd(VoidCallback disposer) { | ||
52 | + TaskManager.instance.reportAdd(disposer); | ||
53 | + } | ||
54 | + | ||
27 | void _notifyUpdate() { | 55 | void _notifyUpdate() { |
28 | for (var element in _updaters!) { | 56 | for (var element in _updaters!) { |
29 | element!(); | 57 | element!(); |
30 | } | 58 | } |
31 | } | 59 | } |
32 | 60 | ||
33 | - void _notifyIdUpdate(Object id) { | ||
34 | - if (_updatersGroupIds!.containsKey(id)) { | ||
35 | - final listGroup = _updatersGroupIds![id]!; | ||
36 | - for (var item in listGroup) { | ||
37 | - item(); | ||
38 | - } | ||
39 | - } | ||
40 | - } | ||
41 | - | ||
42 | - @protected | ||
43 | - void refreshGroup(Object id) { | ||
44 | - assert(_debugAssertNotDisposed()); | ||
45 | - _notifyIdUpdate(id); | ||
46 | - } | 61 | + bool get isDisposed => _updaters == null; |
47 | 62 | ||
48 | bool _debugAssertNotDisposed() { | 63 | bool _debugAssertNotDisposed() { |
49 | assert(() { | 64 | assert(() { |
50 | - if (_updaters == null) { | 65 | + if (isDisposed) { |
51 | throw FlutterError('''A $runtimeType was used after being disposed.\n | 66 | throw FlutterError('''A $runtimeType was used after being disposed.\n |
52 | 'Once you have called dispose() on a $runtimeType, it can no longer be used.'''); | 67 | 'Once you have called dispose() on a $runtimeType, it can no longer be used.'''); |
53 | } | 68 | } |
@@ -56,59 +71,79 @@ mixin ListNotifierMixin on Listenable { | @@ -56,59 +71,79 @@ mixin ListNotifierMixin on Listenable { | ||
56 | return true; | 71 | return true; |
57 | } | 72 | } |
58 | 73 | ||
59 | - @protected | ||
60 | - void notifyChildrens() { | ||
61 | - TaskManager.instance.notify(_updaters); | 74 | + int get listenersLength { |
75 | + assert(_debugAssertNotDisposed()); | ||
76 | + return _updaters!.length; | ||
62 | } | 77 | } |
63 | 78 | ||
64 | - bool get hasListeners { | 79 | + @mustCallSuper |
80 | + void dispose() { | ||
65 | assert(_debugAssertNotDisposed()); | 81 | assert(_debugAssertNotDisposed()); |
66 | - return _updaters!.isNotEmpty; | 82 | + _updaters = null; |
83 | + } | ||
84 | +} | ||
85 | + | ||
86 | +mixin ListNotifierGroupMixin on Listenable { | ||
87 | + HashMap<Object?, ListNotifierSingleMixin>? _updatersGroupIds = | ||
88 | + HashMap<Object?, ListNotifierSingleMixin>(); | ||
89 | + | ||
90 | + void _notifyGroupUpdate(Object id) { | ||
91 | + if (_updatersGroupIds!.containsKey(id)) { | ||
92 | + _updatersGroupIds![id]!._notifyUpdate(); | ||
93 | + } | ||
67 | } | 94 | } |
68 | 95 | ||
69 | - int get listeners { | 96 | + @protected |
97 | + void notifyGroupChildrens(Object id) { | ||
70 | assert(_debugAssertNotDisposed()); | 98 | assert(_debugAssertNotDisposed()); |
71 | - return _updaters!.length; | 99 | + TaskManager.instance.notify(_updatersGroupIds![id]!); |
72 | } | 100 | } |
73 | 101 | ||
74 | - @override | ||
75 | - void removeListener(VoidCallback listener) { | 102 | + bool containsId(Object id) { |
103 | + return _updatersGroupIds?.containsKey(id) ?? false; | ||
104 | + } | ||
105 | + | ||
106 | + @protected | ||
107 | + void refreshGroup(Object id) { | ||
76 | assert(_debugAssertNotDisposed()); | 108 | assert(_debugAssertNotDisposed()); |
77 | - _updaters!.remove(listener); | 109 | + _notifyGroupUpdate(id); |
110 | + } | ||
111 | + | ||
112 | + bool _debugAssertNotDisposed() { | ||
113 | + assert(() { | ||
114 | + if (_updatersGroupIds == null) { | ||
115 | + throw FlutterError('''A $runtimeType was used after being disposed.\n | ||
116 | +'Once you have called dispose() on a $runtimeType, it can no longer be used.'''); | ||
117 | + } | ||
118 | + return true; | ||
119 | + }()); | ||
120 | + return true; | ||
78 | } | 121 | } |
79 | 122 | ||
80 | void removeListenerId(Object id, VoidCallback listener) { | 123 | void removeListenerId(Object id, VoidCallback listener) { |
81 | assert(_debugAssertNotDisposed()); | 124 | assert(_debugAssertNotDisposed()); |
82 | if (_updatersGroupIds!.containsKey(id)) { | 125 | if (_updatersGroupIds!.containsKey(id)) { |
83 | - _updatersGroupIds![id]!.remove(listener); | 126 | + _updatersGroupIds![id]!.removeListener(listener); |
84 | } | 127 | } |
85 | - _updaters!.remove(listener); | ||
86 | } | 128 | } |
87 | 129 | ||
88 | @mustCallSuper | 130 | @mustCallSuper |
89 | void dispose() { | 131 | void dispose() { |
90 | assert(_debugAssertNotDisposed()); | 132 | assert(_debugAssertNotDisposed()); |
91 | - _updaters = null; | 133 | + _updatersGroupIds?.forEach((key, value) => value.dispose()); |
92 | _updatersGroupIds = null; | 134 | _updatersGroupIds = null; |
93 | } | 135 | } |
94 | 136 | ||
95 | - @override | ||
96 | - Disposer addListener(GetStateUpdate listener) { | ||
97 | - assert(_debugAssertNotDisposed()); | ||
98 | - _updaters!.add(listener); | ||
99 | - return () => _updaters!.remove(listener); | ||
100 | - } | ||
101 | - | ||
102 | Disposer addListenerId(Object? key, GetStateUpdate listener) { | 137 | Disposer addListenerId(Object? key, GetStateUpdate listener) { |
103 | - _updatersGroupIds![key] ??= <GetStateUpdate>[]; | ||
104 | - _updatersGroupIds![key]!.add(listener); | ||
105 | - return () => _updatersGroupIds![key]!.remove(listener); | 138 | + _updatersGroupIds![key] ??= ListNotifierSingle(); |
139 | + return _updatersGroupIds![key]!.addListener(listener); | ||
106 | } | 140 | } |
107 | 141 | ||
108 | /// To dispose an [id] from future updates(), this ids are registered | 142 | /// To dispose an [id] from future updates(), this ids are registered |
109 | /// by `GetBuilder()` or similar, so is a way to unlink the state change with | 143 | /// by `GetBuilder()` or similar, so is a way to unlink the state change with |
110 | /// the Widget from the Controller. | 144 | /// the Widget from the Controller. |
111 | void disposeId(Object id) { | 145 | void disposeId(Object id) { |
146 | + _updatersGroupIds?[id]?.dispose(); | ||
112 | _updatersGroupIds!.remove(id); | 147 | _updatersGroupIds!.remove(id); |
113 | } | 148 | } |
114 | } | 149 | } |
@@ -123,11 +158,16 @@ class TaskManager { | @@ -123,11 +158,16 @@ class TaskManager { | ||
123 | GetStateUpdate? _setter; | 158 | GetStateUpdate? _setter; |
124 | List<VoidCallback>? _remove; | 159 | List<VoidCallback>? _remove; |
125 | 160 | ||
126 | - void notify(List<GetStateUpdate?>? _updaters) { | ||
127 | - if (_setter != null) { | ||
128 | - if (!_updaters!.contains(_setter)) { | ||
129 | - _updaters.add(_setter); | ||
130 | - _remove!.add(() => _updaters.remove(_setter)); | 161 | + void reportAdd(VoidCallback listener) { |
162 | + _remove?.add(listener); | ||
163 | + } | ||
164 | + | ||
165 | + void notify(ListNotifierSingleMixin _updaters) { | ||
166 | + final listener = _setter; | ||
167 | + if (listener != null) { | ||
168 | + if (!_updaters.containsListener(listener)) { | ||
169 | + _updaters.addListener(listener); | ||
170 | + reportAdd(() => _updaters.removeListener(listener)); | ||
131 | } | 171 | } |
132 | } | 172 | } |
133 | } | 173 | } |
@@ -136,9 +176,29 @@ class TaskManager { | @@ -136,9 +176,29 @@ class TaskManager { | ||
136 | T Function() builder) { | 176 | T Function() builder) { |
137 | _remove = disposers; | 177 | _remove = disposers; |
138 | _setter = setState; | 178 | _setter = setState; |
179 | + | ||
139 | final result = builder(); | 180 | final result = builder(); |
181 | + print(disposers.isEmpty); | ||
182 | + if (disposers.isEmpty) { | ||
183 | + throw ObxError(); | ||
184 | + } | ||
140 | _remove = null; | 185 | _remove = null; |
141 | _setter = null; | 186 | _setter = null; |
142 | return result; | 187 | return result; |
143 | } | 188 | } |
144 | } | 189 | } |
190 | + | ||
191 | +class ObxError { | ||
192 | + const ObxError(); | ||
193 | + @override | ||
194 | + String toString() { | ||
195 | + return """ | ||
196 | + [Get] the improper use of a GetX has been detected. | ||
197 | + You should only use GetX or Obx for the specific widget that will be updated. | ||
198 | + If you are seeing this error, you probably did not insert any observable variables into GetX/Obx | ||
199 | + or insert them outside the scope that GetX considers suitable for an update | ||
200 | + (example: GetX => HeavyWidget => variableObservable). | ||
201 | + If you need to update a parent widget and a child widget, wrap each one in an Obx/GetX. | ||
202 | + """; | ||
203 | + } | ||
204 | +} |
@@ -78,10 +78,10 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T?>> { | @@ -78,10 +78,10 @@ class _ValueBuilderState<T> extends State<ValueBuilder<T?>> { | ||
78 | class ObxElement = StatelessElement with ObserverComponent; | 78 | class ObxElement = StatelessElement with ObserverComponent; |
79 | 79 | ||
80 | // It's a experimental feature | 80 | // It's a experimental feature |
81 | -class SimpleBuilder extends ObxStatelessWidget { | 81 | +class Observer extends ObxStatelessWidget { |
82 | final WidgetBuilder builder; | 82 | final WidgetBuilder builder; |
83 | 83 | ||
84 | - const SimpleBuilder({Key? key, required this.builder}) : super(key: key); | 84 | + const Observer({Key? key, required this.builder}) : super(key: key); |
85 | 85 | ||
86 | @override | 86 | @override |
87 | Widget build(BuildContext context) => builder(context); | 87 | Widget build(BuildContext context) => builder(context); |
1 | import 'dart:async'; | 1 | import 'dart:async'; |
2 | + | ||
2 | import 'package:flutter/foundation.dart'; | 3 | import 'package:flutter/foundation.dart'; |
3 | import 'package:flutter_test/flutter_test.dart'; | 4 | import 'package:flutter_test/flutter_test.dart'; |
4 | import 'package:get/state_manager.dart'; | 5 | import 'package:get/state_manager.dart'; |
@@ -73,28 +74,28 @@ Future<int> stream() { | @@ -73,28 +74,28 @@ Future<int> stream() { | ||
73 | return c.future; | 74 | return c.future; |
74 | } | 75 | } |
75 | 76 | ||
76 | -Future<int> getStream() { | ||
77 | - final c = Completer<int>(); | 77 | +// Future<int> getStream() { |
78 | +// final c = Completer<int>(); | ||
78 | 79 | ||
79 | - final value = GetStream<int>(); | ||
80 | - final timer = Stopwatch(); | ||
81 | - timer.start(); | 80 | +// final value = GetStream<int>(); |
81 | +// final timer = Stopwatch(); | ||
82 | +// timer.start(); | ||
82 | 83 | ||
83 | - value.listen((v) { | ||
84 | - if (times == v) { | ||
85 | - timer.stop(); | ||
86 | - print( | ||
87 | - """$v listeners notified | [GET_STREAM] time: ${timer.elapsedMicroseconds}ms"""); | ||
88 | - c.complete(timer.elapsedMicroseconds); | ||
89 | - } | ||
90 | - }); | 84 | +// value.listen((v) { |
85 | +// if (times == v) { | ||
86 | +// timer.stop(); | ||
87 | +// print( | ||
88 | +// """$v listeners notified | [GET_STREAM] time: ${timer.elapsedMicroseconds}ms"""); | ||
89 | +// c.complete(timer.elapsedMicroseconds); | ||
90 | +// } | ||
91 | +// }); | ||
91 | 92 | ||
92 | - for (var i = 0; i < times + 1; i++) { | ||
93 | - value.add(i); | ||
94 | - } | 93 | +// for (var i = 0; i < times + 1; i++) { |
94 | +// value.add(i); | ||
95 | +// } | ||
95 | 96 | ||
96 | - return c.future; | ||
97 | -} | 97 | +// return c.future; |
98 | +// } | ||
98 | 99 | ||
99 | Future<int> miniStream() { | 100 | Future<int> miniStream() { |
100 | final c = Completer<int>(); | 101 | final c = Completer<int>(); |
@@ -157,7 +158,7 @@ GetValue is ${calculePercentage(dart, getx).round()}% faster than Default ValueN | @@ -157,7 +158,7 @@ GetValue is ${calculePercentage(dart, getx).round()}% faster than Default ValueN | ||
157 | print('============================================'); | 158 | print('============================================'); |
158 | print('DART STREAM X GET_STREAM X GET_MINI_STREAM TEST'); | 159 | print('DART STREAM X GET_STREAM X GET_MINI_STREAM TEST'); |
159 | print('-----------'); | 160 | print('-----------'); |
160 | - var getx = await getStream(); | 161 | + // var getx = await getStream(); |
161 | var mini = await miniStream(); | 162 | var mini = await miniStream(); |
162 | var dart = await stream(); | 163 | var dart = await stream(); |
163 | print('-----------'); | 164 | print('-----------'); |
@@ -167,16 +168,16 @@ GetStream is ${calculePercentage(dart, mini).round()}% faster than Default Strea | @@ -167,16 +168,16 @@ GetStream is ${calculePercentage(dart, mini).round()}% faster than Default Strea | ||
167 | 168 | ||
168 | times = 30000; | 169 | times = 30000; |
169 | dart = await stream(); | 170 | dart = await stream(); |
170 | - getx = await getStream(); | 171 | + // getx = await getStream(); |
171 | mini = await miniStream(); | 172 | mini = await miniStream(); |
172 | 173 | ||
173 | times = 60000; | 174 | times = 60000; |
174 | dart = await stream(); | 175 | dart = await stream(); |
175 | - getx = await getStream(); | 176 | + // getx = await getStream(); |
176 | mini = await miniStream(); | 177 | mini = await miniStream(); |
177 | print('-----------'); | 178 | print('-----------'); |
178 | print('dart_stream delay $dart ms to made $times requests'); | 179 | print('dart_stream delay $dart ms to made $times requests'); |
179 | - print('getx_stream delay $getx ms to made $times requests'); | 180 | + // print('getx_stream delay $getx ms to made $times requests'); |
180 | print('getx_mini_stream delay $mini ms to made $times requests'); | 181 | print('getx_mini_stream delay $mini ms to made $times requests'); |
181 | print('-----------'); | 182 | print('-----------'); |
182 | print(''' | 183 | print(''' |
-
Please register or login to post a comment