Jonatas

update to 3.16.2

  1 +## [3.16.2]
  2 +- Clean RxList, RxMap and RxSet implementation
  3 +- Now when declaring an `RxList()`, it will be started empty. If you want to start a null RxList, you must use `RxList(null)`.
  4 +Improved GetStream to receive the same parameters as the StreamController, such as `onListen`, `onPause`, `onResume` and `onCancel`.
  5 +- Improve docs
  6 +
1 ## [3.16.1] 7 ## [3.16.1]
2 - Fix compilation error on master 8 - Fix compilation error on master
3 9
@@ -6,7 +12,7 @@ @@ -6,7 +12,7 @@
6 - Added error message callback for StateMixin (@eduardoflorence) 12 - Added error message callback for StateMixin (@eduardoflorence)
7 - Fix incorrect Get.reference when pop route (@4mb1t) 13 - Fix incorrect Get.reference when pop route (@4mb1t)
8 - Added Uppercase/Capital letter on GetUtils (@AleFachini) 14 - Added Uppercase/Capital letter on GetUtils (@AleFachini)
9 -- Redraw the Streams api to use GetStream instead of StreamControllers. Why this change? GetStream is as light as a ValueNotifier, has very low latency and low consumption of RAM and CPU. There are cases where the performance gain exceeds 9000%, making Get unique when it comes to low latency and resource savings. We did this because new devices are being equipped with 120hz refresh rate, and to provide an even smoother reconstruction of the widgets, it was necessary to create a low latency solution from scratch. GetStream was then created, released in the previous version, and improved in that version. In the previous version, only a small part of GetX used this low-latency API so that it was possible to verify solidly if the api was mature enough to equip state management, which is the most used feature of this library. After two weeks of unremitting tests, we realized that in addition to being fast, the new api is reliable, and will even equip the Stable version of GetServer, which due to the low latency will have performance of low level languages ​​close to C, C ++, Rust and GO. 15 +- Redraw the Streams api to use GetStream instead of StreamControllers. Why this change? GetStream is as light as a ValueNotifier, has very low latency and low consumption of RAM and CPU. The performance difference between Standard Stream and GetStream can exceeds 9000% ([run benchmark by yourself](https://github.com/jonataslaw/getx/blob/master/test/benchmarks/benckmark_test.dart)), making Get unique when it comes to low latency and resource savings. We did this because GetServer needed a low latency solution to optimize the rate of requests, and because today's smartphones are being equipped with increasingly higher refresh rates. There are cell phones today that start at a rate of 120Hz, and the low latency ensures that no frames are lost, ensuring better fluidity. GetStream was then created, released in the previous version, and improved in that version. In the previous version, only a small part of GetX used this low-latency API so that it was possible to verify solidly if the api was mature enough to equip state management, which is the most used feature of this library. After two weeks of unremitting tests, we realized that in addition to being fast, the new api is reliable, and will even equip the Stable version of GetServer, which due to the low latency will have performance of low level languages ​​close to C, C ++, Rust and GO.
10 16
11 ## [3.15.0] - Big update 17 ## [3.15.0] - Big update
12 - **Improve Performance**: We made modifications to make GetBuilder even faster. We have improved the structure behind it so that listeners are notified faster. Perhaps in version 4.0 everything will be based on this new structure, but maintaining the power and compatibility with streams. If you want to know how much Getx is faster than pure streams or ChangeNotifier (even after the last update using LinkedList), you can create run the repository tests at: (https://github.com/jonataslaw/getx/blob/master/test/benchmarks/benckmark_test.dart) 18 - **Improve Performance**: We made modifications to make GetBuilder even faster. We have improved the structure behind it so that listeners are notified faster. Perhaps in version 4.0 everything will be based on this new structure, but maintaining the power and compatibility with streams. If you want to know how much Getx is faster than pure streams or ChangeNotifier (even after the last update using LinkedList), you can create run the repository tests at: (https://github.com/jonataslaw/getx/blob/master/test/benchmarks/benckmark_test.dart)
@@ -54,18 +54,22 @@ _Languages: English (this file), [Chinese](README.zh-cn.md), [Brazilian Portugue @@ -54,18 +54,22 @@ _Languages: English (this file), [Chinese](README.zh-cn.md), [Brazilian Portugue
54 54
55 - GetX is an extra-light and powerful solution for Flutter. It combines high performance state management, intelligent dependency injection, and route management in a quick and practical way. 55 - GetX is an extra-light and powerful solution for Flutter. It combines high performance state management, intelligent dependency injection, and route management in a quick and practical way.
56 56
57 -- GetX has 3 basic principles, this means that this is the priority for all resources in the library 57 +- GetX has 3 basic principles, this means that this is the priority for all resources in the library: **PRODUCTIVITY, PERFORMANCE AND ORGANIZATION.**
58 58
59 - - **PERFORMANCE:** GetX is focused on performance and minimum consumption of resources. Benchmarks are almost always not important in the real world, but if you want, there is a consumption indicator here([benchmarks](https://github.com/jonataslaw/benchmarks)), where GetX does better than other state management approaches, for example. The difference is not large, but it shows our concern not to waste its resources.  
60 - - **PRODUCTIVITY:** GetX uses an easy and pleasant syntax. No matter what you want to do, there is always an easier way with Getx. It will save hours of development, and will extract the maximum performance that your application can deliver  
61 - - **ORGANIZATION:** GetX allows the total decoupling of the View, presentation logic, business logic, dependency injection, and navigation. You do not need context to navigate between routes, so you are not dependent on the widget tree (visualization) for this. You don't need context to access your controllers / blocks through an inheritedWidget, so you completely decouple your presentation logic and business logic from your visualization layer. You do not need to inject your Controllers/Models/Blocs classes into your widget tree through multiproviders, for this GetX uses its own dependency injection feature, decoupling the DI from its view completely. 59 + - **PERFORMANCE:** GetX is focused on performance and minimum consumption of resources. GetX does not use Streams or ChangeNotifier like other state managers. Why? In addition to building applications for android, iOS, web, linux, macos and linux, with GetX you can build server applications with the same syntax as Flutter/GetX. In order to improve response time and reduce RAM consumption, we created GetValue and GetStream, which are low latency solutions that deliver a lot of performance, at a low operating cost. We use this base to build all of our resources, including state management. Here ([benchmarks](https://github.com/jonataslaw/getx/blob/master/test/benchmarks/benckmark_test.dart)) there is a test that aims to measure the latency time between ChangeNotifier/GetValue and Streams/GetStreams, specifically measuring the time each of these takes to make 30 to 30,000 status updates. By using simple VoidCallbacks instead of buffering for Streams, RAM consumption is also low. In addition, an application using GetX for state management is also generally smaller than using other approaches. You can test this for yourself using this repository ([state manager approachs](https://github.com/jonataslaw/flutter_state_managers)) that has a simple application with the main state managers of Flutter, which had the collaboration of the creators of each lib, however the difference is small (0.1mb), and you shouldn't choose to use GetX just for that, but mainly because of the two other principles:
  60 +
  61 + - **PRODUCTIVITY:** GetX uses an easy and pleasant syntax. No matter what you want to do, there is always an easier way with Getx. It will save hours of development, and will extract the maximum performance that your application can deliver.
  62 + Generally, the developer should be concerned with removing controllers from memory. With GetX this is not necessary, because resources are removed from memory when they are not used by default. If you want to keep it in memory, you must explicitly declare "permanent: true" in your dependency. That way, in addition to saving time, you are less at risk of having unnecessary dependencies on memory. Dependency loading is also lazy by default.
  63 +
  64 + - **ORGANIZATION:** GetX allows the total decoupling of the View, presentation logic, business logic, dependency injection, and navigation. You do not need context to navigate between routes, so you are not dependent on the widget tree (visualization) for this. You don't need context to access your controllers/blocs through an inheritedWidget, so you completely decouple your presentation logic and business logic from your visualization layer. You do not need to inject your Controllers/Models/Blocs classes into your widget tree through multiproviders, for this GetX uses its own dependency injection feature, decoupling the DI from its view completely.
62 With GetX you know where to find each feature of your application, having clean code by default. This in addition to facilitating maintenance, makes the sharing of modules, something that until then in Flutter was unthinkable, something totally possible. 65 With GetX you know where to find each feature of your application, having clean code by default. This in addition to facilitating maintenance, makes the sharing of modules, something that until then in Flutter was unthinkable, something totally possible.
63 BLoC was a starting point for organizing code in Flutter, it separates business logic from visualization. Getx is a natural evolution of this, not only separating the business logic, but the presentation logic. Bonus injection of dependencies and routes are also decoupled, and the data layer is out of it all. You know where everything is, and all of this in an easier way than building a hello world. 66 BLoC was a starting point for organizing code in Flutter, it separates business logic from visualization. Getx is a natural evolution of this, not only separating the business logic, but the presentation logic. Bonus injection of dependencies and routes are also decoupled, and the data layer is out of it all. You know where everything is, and all of this in an easier way than building a hello world.
64 - GetX is the easiest, most practical and scalable way to build high-performance applications with the Flutter SDK, with a large ecosystem around it that works perfectly together, being easy for beginners, and accurate for experts. It is secure, stable, up-to-date, and offers a huge range of APIs build-in that are not present on default Flutter SDK. 67 + GetX is the easiest, practical and scalable way to build high-performance applications with the Flutter SDK, with a large ecosystem around it that works perfectly together, being easy for beginners, and accurate for experts. It is secure, stable, up-to-date, and offers a huge range of APIs build-in that are not present on default Flutter SDK.
65 68
66 - GetX is not a bloated. It has a multitude of features that allow you to start programming without worrying about anything, but each of these features are in separate containers, and are only started after use. If you only use State Management, only State Management will be compiled. If you only use routes, nothing from the state management will be compiled. You can compile the benchmark repository, and you will see that using only Get state management, the application compiled with Get has become smaller than all other applications that have only the state management of other packages, because nothing that is not used will be compiled into your code, and each GetX solution was designed to be extra lightweight. The merit here also comes from Flutter's tree shaking which is incredible, and manages to eliminate unused resources like no other framework does. 69 - GetX is not a bloated. It has a multitude of features that allow you to start programming without worrying about anything, but each of these features are in separate containers, and are only started after use. If you only use State Management, only State Management will be compiled. If you only use routes, nothing from the state management will be compiled. You can compile the benchmark repository, and you will see that using only Get state management, the application compiled with Get has become smaller than all other applications that have only the state management of other packages, because nothing that is not used will be compiled into your code, and each GetX solution was designed to be extra lightweight. The merit here also comes from Flutter's tree shaking which is incredible, and manages to eliminate unused resources like no other framework does.
  70 +In case you need it, GetX also has separate packages for each resource, but this is probably not necessary, as GetX alone separates the packages in the single library.
67 71
68 -- Getx has a huge ecosystem, capable of running with the same code on Android, iOS, Web, Mac, Linux, Windows, and on your server. 72 +- Getx has a huge ecosystem, a large community, a large number of collaborators, and will be maintained as long as the Flutter exists. Getx too is capable of running with the same code on Android, iOS, Web, Mac, Linux, Windows, and on your server.
69 **It is possible to fully reuse your code made on the frontend on your backend with [Get Server](https://github.com/jonataslaw/get_server)**. 73 **It is possible to fully reuse your code made on the frontend on your backend with [Get Server](https://github.com/jonataslaw/get_server)**.
70 74
71 **In addition, the entire development process can be completely automated, both on the server and on the front end with [Get CLI](https://github.com/jonataslaw/get_cli)**. 75 **In addition, the entire development process can be completely automated, both on the server and on the front end with [Get CLI](https://github.com/jonataslaw/get_cli)**.
@@ -160,13 +164,7 @@ Improve your deadlines, deliver everything on time without losing performance. G @@ -160,13 +164,7 @@ Improve your deadlines, deliver everything on time without losing performance. G
160 164
161 ## State management 165 ## State management
162 166
163 -There are currently several state managers for Flutter. However, most of them involve using ChangeNotifier to update widgets and this is a bad and very bad approach to performance of medium or large applications. You can check in the official Flutter documentation that [ChangeNotifier should be used with 1 or a maximum of 2 listeners](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html), making it practically unusable for any application medium or large.  
164 -  
165 -Get isn't better or worse than any other state manager, but that you should analyze these points as well as the points below to choose between using Get in pure form (Vanilla), or using it in conjunction with another state manager.  
166 -  
167 -Definitely, Get is not the enemy of any other state manager, because Get is a microframework, not just a state manager, and can be used either alone or in conjunction with them.  
168 -  
169 -Get has two different state managers: the simple state manager (we'll call it GetBuilder) and the reactive state manager (who has the package name, GetX) 167 +Get has two different state managers: the simple state manager (we'll call it GetBuilder) and the reactive state manager (GetX/Obx)
170 168
171 ### Reactive State Manager 169 ### Reactive State Manager
172 170
@@ -176,6 +174,7 @@ Reactive programming can alienate many people because it is said to be complicat @@ -176,6 +174,7 @@ Reactive programming can alienate many people because it is said to be complicat
176 - You won't need to create a StreamBuilder for each variable 174 - You won't need to create a StreamBuilder for each variable
177 - You will not need to create a class for each state. 175 - You will not need to create a class for each state.
178 - You will not need to create a get for an initial value. 176 - You will not need to create a get for an initial value.
  177 +- You will not need to use code generators
179 178
180 Reactive programming with Get is as easy as using setState. 179 Reactive programming with Get is as easy as using setState.
181 180
@@ -349,13 +348,11 @@ Get.updateLocale(locale); @@ -349,13 +348,11 @@ Get.updateLocale(locale);
349 348
350 #### System locale 349 #### System locale
351 350
352 -To read the system locale, you could use `window.locale`. 351 +To read the system locale, you could use `Get.deviceLocale`.
353 352
354 ```dart 353 ```dart
355 -import 'dart:ui' as ui;  
356 -  
357 return GetMaterialApp( 354 return GetMaterialApp(
358 - locale: ui.window.locale, 355 + locale: Get.deviceLocale,
359 ); 356 );
360 ``` 357 ```
361 358
1 - [State Management](#state-management) 1 - [State Management](#state-management)
2 - [Reactive State Manager](#reactive-state-manager) 2 - [Reactive State Manager](#reactive-state-manager)
3 - [Advantages](#advantages) 3 - [Advantages](#advantages)
  4 + - [Maximum performance:](#maximum-performance)
4 - [Declaring a reactive variable](#declaring-a-reactive-variable) 5 - [Declaring a reactive variable](#declaring-a-reactive-variable)
  6 + - [Having a reactive state, is easy.](#having-a-reactive-state-is-easy)
5 - [Using the values in the view](#using-the-values-in-the-view) 7 - [Using the values in the view](#using-the-values-in-the-view)
6 - [Conditions to rebuild](#conditions-to-rebuild) 8 - [Conditions to rebuild](#conditions-to-rebuild)
7 - [Where .obs can be used](#where-obs-can-be-used) 9 - [Where .obs can be used](#where-obs-can-be-used)
@@ -22,15 +24,16 @@ @@ -22,15 +24,16 @@
22 24
23 # State Management 25 # State Management
24 26
25 -There are currently several state managers for Flutter. However, most of them involve using ChangeNotifier to update widgets and this is a bad and very bad approach to performance of medium or large applications. You can check in the official Flutter documentation that [ChangeNotifier should be used with 1 or a maximum of 2 listeners](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html), making it practically unusable for any application medium or large. 27 +GetX does not use Streams or ChangeNotifier like other state managers. Why? In addition to building applications for android, iOS, web, linux, macos and linux, with GetX you can build server applications with the same syntax as Flutter/GetX. In order to improve response time and reduce RAM consumption, we created GetValue and GetStream, which are low latency solutions that deliver a lot of performance, at a low operating cost. We use this base to build all of our resources, including state management.
26 28
27 -Other state managers are good, but have their nuances:  
28 -  
29 -- BLoC is very safe and efficient, but it is very complex for beginners, which has kept people from developing with Flutter.  
30 -- MobX is easier than BLoC and reactive, almost perfect, I would say, but you need to use a code generator, that for large applications, reduces productivity, since you will need to drink a lot of coffees until your code is ready again after a `flutter clean` (And this is not MobX's fault, but the codegen which is really slow!).  
31 -- Provider uses InheritedWidget to deliver the same listener, as a way of solving the problem reported above with ChangeNotifier, which implies that any access to its ChangeNotifier class must be within the widget tree because of the context to access o Inherited.  
32 -  
33 -Get isn't better or worse than any other state manager, but that you should analyze these points as well as the points below to choose between using Get in pure form (Vanilla), or using it in conjunction with another state manager. Definitely, Get is not the enemy of any other state manager, because Get is a microframework, not just a state manager, and can be used either alone or in conjunction with them. 29 +- _Complexity_: Some state managers are complex and have a lot of boilerplate. With GetX you don't have to define a class for each event, the code is highly clean and clear, and you do a lot more by writing less. Many people have given up on Flutter because of this topic, and they now finally have a stupidly simple solution for managing states.
  30 +- _No code generators_: You spend half your development time writing your application logic. Some state managers rely on code generators to have minimally readable code. Changing a variable and having to run build_runner can be unproductive, and often the waiting time after a flutter clean will be long, and you will have to drink a lot of coffee.
  31 +With GetX everything is reactive, and nothing depends on code generators, increasing your productivity in all aspects of your development.
  32 +- _It does not depend on context_: You probably already needed to send the context of your view to a controller, making the View's coupling with your business logic high. You have probably had to use a dependency for a place that has no context, and had to pass the context through various classes and functions. This just doesn't exist with GetX. You have access to your controllers from within your controllers without any context. You don't need to send the context by parameter for literally nothing.
  33 +- _Granular control_: most state managers are based on ChangeNotifier. ChangeNotifier will notify all widgets that depend on it when notifyListeners is called. If you have 40 widgets on one screen, which have a variable of your ChangeNotifier class, when you update one, all of them will be rebuilt.
  34 +With GetX, even nested widgets are respected. If you have Obx watching your ListView, and another watching a checkbox inside the ListView, when changing the CheckBox value, only it will be updated, when changing the List value, only the ListView will be updated.
  35 +- _It only reconstructs if its variable REALLY changes_: GetX has flow control, that means if you display a Text with 'Paola', if you change the observable variable to 'Paola' again, the widget will not be reconstructed. That's because GetX knows that 'Paola' is already being displayed in Text, and will not do unnecessary reconstructions.
  36 +Most (if not all) current state managers will rebuild on the screen.
34 37
35 ## Reactive State Manager 38 ## Reactive State Manager
36 39
@@ -1046,6 +1046,8 @@ Since version 2.8 it is possible to access the properties @@ -1046,6 +1046,8 @@ Since version 2.8 it is possible to access the properties
1046 ///The window to which this binding is bound. 1046 ///The window to which this binding is bound.
1047 ui.Window get window => ui.window; 1047 ui.Window get window => ui.window;
1048 1048
  1049 + Locale get deviceLocale => window.locale;
  1050 +
1049 ///The number of device pixels for each logical pixel. 1051 ///The number of device pixels for each logical pixel.
1050 double get pixelRatio => window.devicePixelRatio; 1052 double get pixelRatio => window.devicePixelRatio;
1051 1053
@@ -8,58 +8,12 @@ part of rx_stream; @@ -8,58 +8,12 @@ part of rx_stream;
8 /// to stream. [listen] is a very light StreamSubscription interface. 8 /// to stream. [listen] is a very light StreamSubscription interface.
9 /// Is possible take the last value with [value] property. 9 /// Is possible take the last value with [value] property.
10 class GetStream<T> { 10 class GetStream<T> {
11 - LightListenable<T> listenable = LightListenable<T>(); 11 + void Function() onListen;
  12 + void Function() onPause;
  13 + void Function() onResume;
  14 + FutureOr<void> Function() onCancel;
12 15
13 - T _value;  
14 -  
15 - T get value => _value;  
16 -  
17 - void add(T event) {  
18 - _value = event;  
19 - _checkIfDisposed();  
20 - listenable.notifyData(event);  
21 - }  
22 -  
23 - void _checkIfDisposed([bool isClosed = false]) {  
24 - if (listenable == null) {  
25 - throw '''[LightStream] Error:  
26 -You cannot ${isClosed ? "close" : "add events to"} a closed stream.''';  
27 - }  
28 - }  
29 -  
30 - void addError(Object error, [StackTrace stackTrace]) {  
31 - _checkIfDisposed();  
32 - listenable.notifyError(error, stackTrace);  
33 - }  
34 -  
35 - void close() {  
36 - _checkIfDisposed(true);  
37 - listenable.notifyDone();  
38 - listenable.dispose();  
39 - listenable = null;  
40 - _value = null;  
41 - }  
42 -  
43 - int get length => listenable.length;  
44 -  
45 - bool get hasListeners => listenable.hasListeners;  
46 -  
47 - bool get isClosed => listenable == null;  
48 -  
49 - LightSubscription<T> listen(void Function(T event) onData,  
50 - {Function onError, void Function() onDone, bool cancelOnError}) {  
51 - final subs = LightSubscription<T>(listenable)  
52 - ..onData(onData)  
53 - ..onError(onError)  
54 - ..onDone(onDone);  
55 - listenable.addSubscription(subs);  
56 - return subs;  
57 - }  
58 -  
59 - Stream<T> get stream => GetStreamTransformation(listenable);  
60 -}  
61 -  
62 -class LightListenable<T> { 16 + GetStream({this.onListen, this.onPause, this.onResume, this.onCancel});
63 List<LightSubscription<T>> _onData = <LightSubscription<T>>[]; 17 List<LightSubscription<T>> _onData = <LightSubscription<T>>[];
64 18
65 bool _isBusy = false; 19 bool _isBusy = false;
@@ -69,7 +23,7 @@ class LightListenable<T> { @@ -69,7 +23,7 @@ class LightListenable<T> {
69 return _onData.remove(subs); 23 return _onData.remove(subs);
70 } else { 24 } else {
71 await Future.delayed(Duration.zero); 25 await Future.delayed(Duration.zero);
72 - return _onData.remove(subs); 26 + return _onData?.remove(subs);
73 } 27 }
74 } 28 }
75 29
@@ -86,70 +40,114 @@ class LightListenable<T> { @@ -86,70 +40,114 @@ class LightListenable<T> {
86 40
87 bool get hasListeners => _onData.isNotEmpty; 41 bool get hasListeners => _onData.isNotEmpty;
88 42
89 - void notifyData(T data) {  
90 - assert(!isDisposed, 'You cannot add data to a closed stream.'); 43 + void _notifyData(T data) {
91 _isBusy = true; 44 _isBusy = true;
92 for (final item in _onData) { 45 for (final item in _onData) {
93 - if (item.isPaused) {  
94 - break;  
95 - } 46 + if (!item.isPaused) {
96 item._data?.call(data); 47 item._data?.call(data);
97 } 48 }
  49 + }
98 _isBusy = false; 50 _isBusy = false;
99 } 51 }
100 52
101 - void notifyError(Object error, [StackTrace stackTrace]) {  
102 - assert(!isDisposed, 'You cannot add errors to a closed stream.'); 53 + void _notifyError(Object error, [StackTrace stackTrace]) {
  54 + assert(!isClosed, 'You cannot add errors to a closed stream.');
103 _isBusy = true; 55 _isBusy = true;
  56 + var itemsToRemove = <LightSubscription<T>>[];
104 for (final item in _onData) { 57 for (final item in _onData) {
105 - if (item.isPaused) {  
106 - break;  
107 - } 58 + if (!item.isPaused) {
108 item._onError?.call(error, stackTrace); 59 item._onError?.call(error, stackTrace);
109 if (item.cancelOnError) { 60 if (item.cancelOnError) {
110 - item.cancel?.call(); 61 + //item.cancel?.call();
  62 + itemsToRemove.add(item);
  63 + item.pause();
111 item._onDone?.call(); 64 item._onDone?.call();
112 } 65 }
113 } 66 }
  67 + }
  68 + for (final item in itemsToRemove) {
  69 + _onData.remove(item);
  70 + }
114 _isBusy = false; 71 _isBusy = false;
115 } 72 }
116 73
117 - void notifyDone() {  
118 - assert(!isDisposed, 'You cannot close a closed stream.'); 74 + void _notifyDone() {
  75 + assert(!isClosed, 'You cannot close a closed stream.');
119 _isBusy = true; 76 _isBusy = true;
120 for (final item in _onData) { 77 for (final item in _onData) {
121 - if (item.isPaused) {  
122 - break;  
123 - } 78 + if (!item.isPaused) {
124 item._onDone?.call(); 79 item._onDone?.call();
125 } 80 }
  81 + }
126 _isBusy = false; 82 _isBusy = false;
127 } 83 }
128 84
129 - void dispose() { 85 + T _value;
  86 +
  87 + T get value => _value;
  88 +
  89 + void add(T event) {
  90 + assert(!isClosed, 'You cannot add event to closed Stream');
  91 + _value = event;
  92 + _notifyData(event);
  93 + }
  94 +
  95 + bool get isClosed => _onData == null;
  96 +
  97 + void addError(Object error, [StackTrace stackTrace]) {
  98 + assert(!isClosed, 'You cannot add error to closed Stream');
  99 + _notifyError(error, stackTrace);
  100 + }
  101 +
  102 + void close() {
  103 + assert(!isClosed, 'You cannot close a closed Stream');
  104 + _notifyDone();
130 _onData = null; 105 _onData = null;
131 _isBusy = null; 106 _isBusy = null;
  107 + _value = null;
  108 + }
  109 +
  110 + LightSubscription<T> listen(void Function(T event) onData,
  111 + {Function onError, void Function() onDone, bool cancelOnError}) {
  112 + final subs = LightSubscription<T>(
  113 + removeSubscription,
  114 + onPause: onPause,
  115 + onResume: onResume,
  116 + onCancel: onCancel,
  117 + )
  118 + ..onData(onData)
  119 + ..onError(onError)
  120 + ..onDone(onDone)
  121 + ..cancelOnError = cancelOnError;
  122 + addSubscription(subs);
  123 + onListen?.call();
  124 + return subs;
132 } 125 }
133 126
134 - bool get isDisposed => _onData == null; 127 + Stream<T> get stream =>
  128 + GetStreamTransformation(addSubscription, removeSubscription);
135 } 129 }
136 130
137 class LightSubscription<T> extends StreamSubscription<T> { 131 class LightSubscription<T> extends StreamSubscription<T> {
138 - final LightListenable<T> listener;  
139 -  
140 - LightSubscription(this.listener); 132 + final RemoveSubscription<T> _removeSubscription;
  133 + LightSubscription(this._removeSubscription,
  134 + {this.onPause, this.onResume, this.onCancel});
  135 + final void Function() onPause;
  136 + final void Function() onResume;
  137 + final FutureOr<void> Function() onCancel;
141 138
142 bool cancelOnError = false; 139 bool cancelOnError = false;
143 140
144 @override 141 @override
145 Future<void> cancel() { 142 Future<void> cancel() {
146 - listener.removeSubscription(this); 143 + _removeSubscription(this);
  144 + onCancel?.call();
147 return Future.value(); 145 return Future.value();
148 } 146 }
149 147
150 OnData<T> _data; 148 OnData<T> _data;
151 149
152 - Function _onError; 150 + dynamic _onError;
153 151
154 Callback _onDone; 152 Callback _onDone;
155 153
@@ -165,10 +163,16 @@ class LightSubscription<T> extends StreamSubscription<T> { @@ -165,10 +163,16 @@ class LightSubscription<T> extends StreamSubscription<T> {
165 void onDone(Callback handleDone) => _onDone = handleDone; 163 void onDone(Callback handleDone) => _onDone = handleDone;
166 164
167 @override 165 @override
168 - void pause([Future<void> resumeSignal]) => _isPaused = true; 166 + void pause([Future<void> resumeSignal]) {
  167 + _isPaused = true;
  168 + onPause?.call();
  169 + }
169 170
170 @override 171 @override
171 - void resume() => _isPaused = false; 172 + void resume() {
  173 + _isPaused = false;
  174 + onResume?.call();
  175 + }
172 176
173 @override 177 @override
174 bool get isPaused => _isPaused; 178 bool get isPaused => _isPaused;
@@ -178,18 +182,23 @@ class LightSubscription<T> extends StreamSubscription<T> { @@ -178,18 +182,23 @@ class LightSubscription<T> extends StreamSubscription<T> {
178 } 182 }
179 183
180 class GetStreamTransformation<T> extends Stream<T> { 184 class GetStreamTransformation<T> extends Stream<T> {
181 - final LightListenable<T> listenable;  
182 -  
183 - GetStreamTransformation(this.listenable); 185 + final AddSubscription<T> _addSubscription;
  186 + final RemoveSubscription<T> _removeSubscription;
  187 + GetStreamTransformation(this._addSubscription, this._removeSubscription);
184 188
185 @override 189 @override
186 LightSubscription<T> listen(void Function(T event) onData, 190 LightSubscription<T> listen(void Function(T event) onData,
187 {Function onError, void Function() onDone, bool cancelOnError}) { 191 {Function onError, void Function() onDone, bool cancelOnError}) {
188 - final subs = LightSubscription<T>(listenable) 192 + final subs = LightSubscription<T>(_removeSubscription)
189 ..onData(onData) 193 ..onData(onData)
190 ..onError(onError) 194 ..onError(onError)
191 ..onDone(onDone); 195 ..onDone(onDone);
192 - listenable.addSubscription(subs); 196 + _addSubscription(subs);
193 return subs; 197 return subs;
194 } 198 }
195 } 199 }
  200 +
  201 +typedef RemoveSubscription<T> = FutureOr<bool> Function(
  202 + LightSubscription<T> subs);
  203 +
  204 +typedef AddSubscription<T> = FutureOr<void> Function(LightSubscription<T> subs);
@@ -110,7 +110,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> { @@ -110,7 +110,7 @@ mixin RxObjectMixin<T> on NotifyManager<T> {
110 return _value; 110 return _value;
111 } 111 }
112 112
113 - Stream<T> get stream => GetStreamTransformation<T>(subject.listenable); 113 + Stream<T> get stream => subject.stream;
114 114
115 /// Binds an existing [Stream<T>] to this Rx<T> to keep the values in sync. 115 /// Binds an existing [Stream<T>] to this Rx<T> to keep the values in sync.
116 /// You can bind multiple sources to update the value. 116 /// You can bind multiple sources to update the value.
@@ -4,8 +4,10 @@ part of rx_types; @@ -4,8 +4,10 @@ part of rx_types;
4 class RxList<E> extends ListMixin<E> 4 class RxList<E> extends ListMixin<E>
5 with NotifyManager<List<E>>, RxObjectMixin<List<E>> 5 with NotifyManager<List<E>>, RxObjectMixin<List<E>>
6 implements RxInterface<List<E>> { 6 implements RxInterface<List<E>> {
7 - RxList([List<E> initial]) {  
8 - _value = initial; 7 + RxList([List<E> initial = const []]) {
  8 + if (initial != null) {
  9 + _value = List.from(initial);
  10 + }
9 } 11 }
10 12
11 @override 13 @override
@@ -130,442 +132,10 @@ class RxList<E> extends ListMixin<E> @@ -130,442 +132,10 @@ class RxList<E> extends ListMixin<E>
130 } 132 }
131 } 133 }
132 134
133 -// /// Create a list similar to `List<T>`  
134 -// class RxList<E> implements List<E>, RxInterface<List<E>> {  
135 -// RxList([List<E> initial]) {  
136 -// if (initial != null) _value = initial;  
137 -// }  
138 -  
139 -// List<E> _value = <E>[];  
140 -  
141 -// @override  
142 -// Iterator<E> get iterator => value.iterator;  
143 -  
144 -// @override  
145 -// bool get isEmpty => value.isEmpty;  
146 -  
147 -// bool get canUpdate {  
148 -// return _subscriptions.length > 0;  
149 -// }  
150 -  
151 -// @override  
152 -// bool get isNotEmpty => value.isNotEmpty;  
153 -  
154 -// @override  
155 -// StreamController<List<E>> subject = StreamController.broadcast();  
156 -  
157 -// final _subscriptions = HashMap<Stream<List<E>>, StreamSubscription>();  
158 -  
159 -// void operator []=(int index, E val) {  
160 -// _value[index] = val;  
161 -// refresh();  
162 -// }  
163 -  
164 -// void refresh() {  
165 -// subject.add(_value);  
166 -// }  
167 -  
168 -// /// Special override to push() element(s) in a reactive way  
169 -// /// inside the List,  
170 -// RxList<E> operator +(Iterable<E> val) {  
171 -// addAll(val);  
172 -// refresh();  
173 -// return this;  
174 -// }  
175 -  
176 -// E operator [](int index) {  
177 -// return value[index];  
178 -// }  
179 -  
180 -// void add(E item) {  
181 -// _value.add(item);  
182 -// refresh();  
183 -// }  
184 -  
185 -// @override  
186 -// void addAll(Iterable<E> item) {  
187 -// _value.addAll(item);  
188 -// refresh();  
189 -// }  
190 -  
191 -// /// Add [item] to [List<E>] only if [item] is not null.  
192 -// void addNonNull(E item) {  
193 -// if (item != null) add(item);  
194 -// }  
195 -  
196 -// /// Add [Iterable<E>] to [List<E>] only if [Iterable<E>] is not null.  
197 -// void addAllNonNull(Iterable<E> item) {  
198 -// if (item != null) addAll(item);  
199 -// }  
200 -  
201 -// /// Add [item] to [List<E>] only if [condition] is true.  
202 -// void addIf(dynamic condition, E item) {  
203 -// if (condition is Condition) condition = condition();  
204 -// if (condition is bool && condition) add(item);  
205 -// }  
206 -  
207 -// /// Adds [Iterable<E>] to [List<E>] only if [condition] is true.  
208 -// void addAllIf(dynamic condition, Iterable<E> items) {  
209 -// if (condition is Condition) condition = condition();  
210 -// if (condition is bool && condition) addAll(items);  
211 -// }  
212 -  
213 -// @override  
214 -// void insert(int index, E item) {  
215 -// _value.insert(index, item);  
216 -// refresh();  
217 -// }  
218 -  
219 -// @override  
220 -// void insertAll(int index, Iterable<E> iterable) {  
221 -// _value.insertAll(index, iterable);  
222 -// refresh();  
223 -// }  
224 -  
225 -// @override  
226 -// int get length => value.length;  
227 -  
228 -// /// Removes an item from the list.  
229 -// ///  
230 -// /// This is O(N) in the number of items in the list.  
231 -// ///  
232 -// /// Returns whether the item was present in the list.  
233 -// @override  
234 -// bool remove(Object item) {  
235 -// final hasRemoved = _value.remove(item);  
236 -// if (hasRemoved) {  
237 -// refresh();  
238 -// }  
239 -// return hasRemoved;  
240 -// }  
241 -  
242 -// @override  
243 -// E removeAt(int index) {  
244 -// final item = _value.removeAt(index);  
245 -// refresh();  
246 -// return item;  
247 -// }  
248 -  
249 -// @override  
250 -// E removeLast() {  
251 -// final item = _value.removeLast();  
252 -// refresh();  
253 -// return item;  
254 -// }  
255 -  
256 -// @override  
257 -// void removeRange(int start, int end) {  
258 -// _value.removeRange(start, end);  
259 -// refresh();  
260 -// }  
261 -  
262 -// @override  
263 -// void removeWhere(bool Function(E) test) {  
264 -// _value.removeWhere(test);  
265 -// refresh();  
266 -// }  
267 -  
268 -// @override  
269 -// void clear() {  
270 -// _value.clear();  
271 -// refresh();  
272 -// }  
273 -  
274 -// @override  
275 -// void sort([int compare(E a, E b)]) {  
276 -// _value.sort(compare);  
277 -// refresh();  
278 -// }  
279 -  
280 -// @override  
281 -// void close() {  
282 -// _subscriptions.forEach((observable, subscription) {  
283 -// subscription.cancel();  
284 -// });  
285 -// _subscriptions.clear();  
286 -// subject.close();  
287 -// }  
288 -  
289 -// /// Replaces all existing items of this list with [item]  
290 -// void assign(E item) {  
291 -// clear();  
292 -// add(item);  
293 -// }  
294 -  
295 -// void update(void fn(Iterable<E> value)) {  
296 -// fn(value);  
297 -// refresh();  
298 -// }  
299 -  
300 -// /// Replaces all existing items of this list with [items]  
301 -// void assignAll(Iterable<E> items) {  
302 -// clear();  
303 -// addAll(items);  
304 -// }  
305 -  
306 -// @protected  
307 -// List<E> get value {  
308 -// if (getObs != null) {  
309 -// getObs.addListener(subject.stream);  
310 -// }  
311 -// return _value;  
312 -// }  
313 -  
314 -// String get string => value.toString();  
315 -  
316 -// void addListener(Stream<List<E>> rxGetX) {  
317 -// if (_subscriptions.containsKey(rxGetX)) {  
318 -// return;  
319 -// }  
320 -// _subscriptions[rxGetX] = rxGetX.listen(subject.add);  
321 -// }  
322 -  
323 -// set value(List<E> val) {  
324 -// if (_value == val) return;  
325 -// _value = val;  
326 -// refresh();  
327 -// }  
328 -  
329 -// Stream<List<E>> get stream => subject.stream;  
330 -  
331 -// StreamSubscription<List<E>> listen(  
332 -// void Function(List<E>) onData, {  
333 -// Function onError,  
334 -// void Function() onDone,  
335 -// bool cancelOnError,  
336 -// }) =>  
337 -// stream.listen(onData, onError: onError, onDone: onDone);  
338 -  
339 -// /// Binds an existing [Stream<List>] to this [RxList].  
340 -// /// You can bind multiple sources to update the value.  
341 -// /// Closing the subscription will happen automatically when the observer  
342 -// /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.  
343 -// void bindStream(Stream<List<E>> stream) {  
344 -// _subscriptions[stream] = stream.listen((va) => value = va);  
345 -// }  
346 -  
347 -// @override  
348 -// E get first => value.first;  
349 -  
350 -// @override  
351 -// E get last => value.last;  
352 -  
353 -// @override  
354 -// bool any(bool Function(E) test) {  
355 -// return value.any(test);  
356 -// }  
357 -  
358 -// @override  
359 -// Map<int, E> asMap() {  
360 -// return value.asMap();  
361 -// }  
362 -  
363 -// @override  
364 -// List<R> cast<R>() {  
365 -// return value.cast<R>();  
366 -// }  
367 -  
368 -// @override  
369 -// bool contains(Object element) {  
370 -// return value.contains(element);  
371 -// }  
372 -  
373 -// @override  
374 -// E elementAt(int index) {  
375 -// return value.elementAt(index);  
376 -// }  
377 -  
378 -// @override  
379 -// bool every(bool Function(E) test) {  
380 -// return value.every(test);  
381 -// }  
382 -  
383 -// @override  
384 -// Iterable<T> expand<T>(Iterable<T> Function(E) f) {  
385 -// return value.expand(f);  
386 -// }  
387 -  
388 -// @override  
389 -// void fillRange(int start, int end, [E fillValue]) {  
390 -// _value.fillRange(start, end, fillValue);  
391 -// refresh();  
392 -// }  
393 -  
394 -// @override  
395 -// E firstWhere(bool Function(E) test, {E Function() orElse}) {  
396 -// return value.firstWhere(test, orElse: orElse);  
397 -// }  
398 -  
399 -// @override  
400 -// T fold<T>(T initialValue, T Function(T, E) combine) {  
401 -// return value.fold(initialValue, combine);  
402 -// }  
403 -  
404 -// @override  
405 -// Iterable<E> followedBy(Iterable<E> other) {  
406 -// return value.followedBy(other);  
407 -// }  
408 -  
409 -// @override  
410 -// void forEach(void Function(E) f) {  
411 -// value.forEach(f);  
412 -// }  
413 -  
414 -// @override  
415 -// Iterable<E> getRange(int start, int end) {  
416 -// return value.getRange(start, end);  
417 -// }  
418 -  
419 -// @override  
420 -// int indexOf(E element, [int start = 0]) {  
421 -// return value.indexOf(element, start);  
422 -// }  
423 -  
424 -// @override  
425 -// int indexWhere(bool Function(E) test, [int start = 0]) {  
426 -// return value.indexWhere(test, start);  
427 -// }  
428 -  
429 -// @override  
430 -// String join([String separator = ""]) {  
431 -// return value.join(separator);  
432 -// }  
433 -  
434 -// @override  
435 -// int lastIndexOf(E element, [int start]) {  
436 -// return value.lastIndexOf(element, start);  
437 -// }  
438 -  
439 -// @override  
440 -// int lastIndexWhere(bool Function(E) test, [int start]) {  
441 -// return value.lastIndexWhere(test, start);  
442 -// }  
443 -  
444 -// @override  
445 -// E lastWhere(bool Function(E) test, {E Function() orElse}) {  
446 -// return value.lastWhere(test, orElse: orElse);  
447 -// }  
448 -  
449 -// @override  
450 -// set length(int newLength) {  
451 -// _value.length = newLength;  
452 -// refresh();  
453 -// }  
454 -  
455 -// @override  
456 -// Iterable<T> map<T>(T Function(E) f) {  
457 -// return value.map(f);  
458 -// }  
459 -  
460 -// @override  
461 -// E reduce(E Function(E, E) combine) {  
462 -// return value.reduce(combine);  
463 -// }  
464 -  
465 -// @override  
466 -// void replaceRange(int start, int end, Iterable<E> replacement) {  
467 -// _value.replaceRange(start, end, replacement);  
468 -// refresh();  
469 -// }  
470 -  
471 -// @override  
472 -// void retainWhere(bool Function(E) test) {  
473 -// _value.retainWhere(test);  
474 -// refresh();  
475 -// }  
476 -  
477 -// @override  
478 -// Iterable<E> get reversed => value.reversed;  
479 -  
480 -// @override  
481 -// void setAll(int index, Iterable<E> iterable) {  
482 -// _value.setAll(index, iterable);  
483 -// refresh();  
484 -// }  
485 -  
486 -// @override  
487 -// void setRange(int start, int end,  
488 -// Iterable<E> iterable, [int skipCount = 0],) {  
489 -// _value.setRange(start, end, iterable, skipCount);  
490 -// refresh();  
491 -// }  
492 -  
493 -// @override  
494 -// void shuffle([Random random]) {  
495 -// _value.shuffle(random);  
496 -// refresh();  
497 -// }  
498 -  
499 -// @override  
500 -// E get single => value.single;  
501 -  
502 -// @override  
503 -// E singleWhere(bool Function(E) test, {E Function() orElse}) {  
504 -// return value.singleWhere(test, orElse: orElse);  
505 -// }  
506 -  
507 -// @override  
508 -// Iterable<E> skip(int count) {  
509 -// return value.skip(count);  
510 -// }  
511 -  
512 -// @override  
513 -// Iterable<E> skipWhile(bool Function(E) test) {  
514 -// return value.skipWhile(test);  
515 -// }  
516 -  
517 -// @override  
518 -// List<E> sublist(int start, [int end]) {  
519 -// return value.sublist(start, end);  
520 -// }  
521 -  
522 -// @override  
523 -// Iterable<E> take(int count) {  
524 -// return value.take(count);  
525 -// }  
526 -  
527 -// @override  
528 -// Iterable<E> takeWhile(bool Function(E) test) {  
529 -// return value.takeWhile(test);  
530 -// }  
531 -  
532 -// @override  
533 -// List<E> toList({bool growable = true}) {  
534 -// return value.toList(growable: growable);  
535 -// }  
536 -  
537 -// @override  
538 -// Set<E> toSet() {  
539 -// return value.toSet();  
540 -// }  
541 -  
542 -// @override  
543 -// Iterable<E> where(bool Function(E) test) {  
544 -// return value.where(test);  
545 -// }  
546 -  
547 -// @override  
548 -// Iterable<T> whereType<T>() {  
549 -// return value.whereType<T>();  
550 -// }  
551 -  
552 -// @override  
553 -// set first(E value) {  
554 -// _value.first = value;  
555 -// refresh();  
556 -// }  
557 -  
558 -// @override  
559 -// set last(E value) {  
560 -// _value.last = value;  
561 -// refresh();  
562 -// }  
563 -// }  
564 -  
565 extension ListExtension<E> on List<E> { 135 extension ListExtension<E> on List<E> {
566 RxList<E> get obs { 136 RxList<E> get obs {
567 if (this != null) { 137 if (this != null) {
568 - return RxList<E>(<E>[])..addAllNonNull(this); 138 + return RxList<E>(this);
569 } else { 139 } else {
570 return RxList<E>(null); 140 return RxList<E>(null);
571 } 141 }
@@ -3,8 +3,10 @@ part of rx_types; @@ -3,8 +3,10 @@ part of rx_types;
3 class RxMap<K, V> extends MapMixin<K, V> 3 class RxMap<K, V> extends MapMixin<K, V>
4 with NotifyManager<Map<K, V>>, RxObjectMixin<Map<K, V>> 4 with NotifyManager<Map<K, V>>, RxObjectMixin<Map<K, V>>
5 implements RxInterface<Map<K, V>> { 5 implements RxInterface<Map<K, V>> {
6 - RxMap([Map<K, V> initial]) {  
7 - _value = initial; 6 + RxMap([Map<K, V> initial = const {}]) {
  7 + if (initial != null) {
  8 + _value = Map.from(initial);
  9 + }
8 } 10 }
9 11
10 @override 12 @override
@@ -3,8 +3,10 @@ part of rx_types; @@ -3,8 +3,10 @@ part of rx_types;
3 class RxSet<E> extends SetMixin<E> 3 class RxSet<E> extends SetMixin<E>
4 with NotifyManager<Set<E>>, RxObjectMixin<Set<E>> 4 with NotifyManager<Set<E>>, RxObjectMixin<Set<E>>
5 implements RxInterface<Set<E>> { 5 implements RxInterface<Set<E>> {
6 - RxSet([Set<E> initial]) {  
7 - if (initial != null) _value = initial; 6 + RxSet([Set<E> initial = const {}]) {
  7 + if (initial != null) {
  8 + _value = Set.from(initial);
  9 + }
8 } 10 }
9 11
10 /// Adds [item] only if [condition] resolves to true. 12 /// Adds [item] only if [condition] resolves to true.
@@ -139,333 +141,6 @@ class RxSet<E> extends SetMixin<E> @@ -139,333 +141,6 @@ class RxSet<E> extends SetMixin<E>
139 } 141 }
140 } 142 }
141 143
142 -// class RxSet<E> implements Set<E>, RxInterface<Set<E>> {  
143 -// RxSet([Set<E> initial]) {  
144 -// if (initial != null) _value = initial;  
145 -// }  
146 -  
147 -// Set<E> _value = <E>{};  
148 -  
149 -// @override  
150 -// Iterator<E> get iterator => value.iterator;  
151 -  
152 -// @override  
153 -// bool get isEmpty => value.isEmpty;  
154 -  
155 -// bool get canUpdate {  
156 -// return _subscriptions.length > 0;  
157 -// }  
158 -  
159 -// @override  
160 -// bool get isNotEmpty => value.isNotEmpty;  
161 -  
162 -// StreamController<Set<E>> subject = StreamController<Set<E>>.broadcast();  
163 -// final _subscriptions = HashMap<Stream<Set<E>>, StreamSubscription>();  
164 -  
165 -// /// Adds [item] only if [condition] resolves to true.  
166 -// void addIf(dynamic condition, E item) {  
167 -// if (condition is Condition) condition = condition();  
168 -// if (condition is bool && condition) add(item);  
169 -// }  
170 -  
171 -// /// Adds all [items] only if [condition] resolves to true.  
172 -// void addAllIf(dynamic condition, Iterable<E> items) {  
173 -// if (condition is Condition) condition = condition();  
174 -// if (condition is bool && condition) addAll(items);  
175 -// }  
176 -  
177 -// void refresh() {  
178 -// subject.add(_value);  
179 -// }  
180 -  
181 -// /// Special override to push() element(s) in a reactive way  
182 -// /// inside the List,  
183 -// RxSet<E> operator +(Set<E> val) {  
184 -// addAll(val);  
185 -// refresh();  
186 -// return this;  
187 -// }  
188 -  
189 -// @override  
190 -// bool add(E value) {  
191 -// final val = _value.add(value);  
192 -// refresh();  
193 -// return val;  
194 -// }  
195 -  
196 -// @override  
197 -// void addAll(Iterable<E> item) {  
198 -// _value.addAll(item);  
199 -// refresh();  
200 -// }  
201 -  
202 -// /// Adds only if [item] is not null.  
203 -// void addNonNull(E item) {  
204 -// if (item != null) add(item);  
205 -// }  
206 -  
207 -// /// Adds only if [item] is not null.  
208 -// void addAllNonNull(Iterable<E> item) {  
209 -// if (item != null) addAll(item);  
210 -// }  
211 -  
212 -// int get length => value.length;  
213 -  
214 -// /// Removes an item from the list.  
215 -// ///  
216 -// /// This is O(N) in the number of items in the list.  
217 -// ///  
218 -// /// Returns whether the item was present in the list.  
219 -// bool remove(Object item) {  
220 -// var hasRemoved = _value.remove(item);  
221 -// if (hasRemoved) {  
222 -// refresh();  
223 -// }  
224 -// return hasRemoved;  
225 -// }  
226 -  
227 -// void removeWhere(bool Function(E) test) {  
228 -// _value.removeWhere(test);  
229 -// refresh();  
230 -// }  
231 -  
232 -// void clear() {  
233 -// _value.clear();  
234 -// refresh();  
235 -// }  
236 -  
237 -// void close() {  
238 -// _subscriptions.forEach((observable, subscription) {  
239 -// subscription.cancel();  
240 -// });  
241 -// _subscriptions.clear();  
242 -// subject.close();  
243 -// }  
244 -  
245 -// /// Replaces all existing items of this list with [item]  
246 -// void assign(E item) {  
247 -// clear();  
248 -// add(item);  
249 -// }  
250 -  
251 -// void update(void fn(Iterable<E> value)) {  
252 -// fn(value);  
253 -// refresh();  
254 -// }  
255 -  
256 -// /// Replaces all existing items of this list with [items]  
257 -// void assignAll(Iterable<E> items) {  
258 -// clear();  
259 -// addAll(items);  
260 -// }  
261 -  
262 -// @protected  
263 -// Set<E> get value {  
264 -// if (getObs != null) {  
265 -// getObs.addListener(subject.stream);  
266 -// }  
267 -// return _value;  
268 -// }  
269 -  
270 -// String get string => value.toString();  
271 -  
272 -// void addListener(Stream<Set<E>> rxGetX) {  
273 -// if (_subscriptions.containsKey(rxGetX)) {  
274 -// return;  
275 -// }  
276 -// _subscriptions[rxGetX] = rxGetX.listen((data) {  
277 -// subject.add(data);  
278 -// });  
279 -// }  
280 -  
281 -// set value(Set<E> val) {  
282 -// if (_value == val) return;  
283 -// _value = val;  
284 -// refresh();  
285 -// }  
286 -  
287 -// Stream<Set<E>> get stream => subject.stream;  
288 -  
289 -// StreamSubscription<Set<E>> listen(void Function(Set<E>) onData,  
290 -// {Function onError, void Function() onDone, bool cancelOnError}) =>  
291 -// stream.listen(onData, onError: onError, onDone: onDone);  
292 -  
293 -// /// Binds an existing [Stream<Set>] to this [RxSet].  
294 -// /// You can bind multiple sources to update the value.  
295 -// /// Closing the subscription will happen automatically when the observer  
296 -// /// Widget ([GetX] or [Obx]) gets unmounted from the Widget tree.  
297 -// void bindStream(Stream<Set<E>> stream) {  
298 -// _subscriptions[stream] = stream.listen((va) => value = va);  
299 -// }  
300 -  
301 -// @override  
302 -// E get first => value.first;  
303 -  
304 -// @override  
305 -// E get last => value.last;  
306 -  
307 -// @override  
308 -// bool any(bool Function(E) test) {  
309 -// return value.any(test);  
310 -// }  
311 -  
312 -// @override  
313 -// Set<R> cast<R>() {  
314 -// return value.cast<R>();  
315 -// }  
316 -  
317 -// @override  
318 -// bool contains(Object element) {  
319 -// return value.contains(element);  
320 -// }  
321 -  
322 -// @override  
323 -// E elementAt(int index) {  
324 -// return value.elementAt(index);  
325 -// }  
326 -  
327 -// @override  
328 -// bool every(bool Function(E) test) {  
329 -// return value.every(test);  
330 -// }  
331 -  
332 -// @override  
333 -// Iterable<T> expand<T>(Iterable<T> Function(E) f) {  
334 -// return value.expand(f);  
335 -// }  
336 -  
337 -// @override  
338 -// E firstWhere(bool Function(E) test, {E Function() orElse}) {  
339 -// return value.firstWhere(test, orElse: orElse);  
340 -// }  
341 -  
342 -// @override  
343 -// T fold<T>(T initialValue, T Function(T, E) combine) {  
344 -// return value.fold(initialValue, combine);  
345 -// }  
346 -  
347 -// @override  
348 -// Iterable<E> followedBy(Iterable<E> other) {  
349 -// return value.followedBy(other);  
350 -// }  
351 -  
352 -// @override  
353 -// void forEach(void Function(E) f) {  
354 -// value.forEach(f);  
355 -// }  
356 -  
357 -// @override  
358 -// String join([String separator = ""]) {  
359 -// return value.join(separator);  
360 -// }  
361 -  
362 -// @override  
363 -// E lastWhere(bool Function(E) test, {E Function() orElse}) {  
364 -// return value.lastWhere(test, orElse: orElse);  
365 -// }  
366 -  
367 -// @override  
368 -// Iterable<T> map<T>(T Function(E) f) {  
369 -// return value.map(f);  
370 -// }  
371 -  
372 -// @override  
373 -// E reduce(E Function(E, E) combine) {  
374 -// return value.reduce(combine);  
375 -// }  
376 -  
377 -// @override  
378 -// E get single => value.single;  
379 -  
380 -// @override  
381 -// E singleWhere(bool Function(E) test, {E Function() orElse}) {  
382 -// return value.singleWhere(test, orElse: orElse);  
383 -// }  
384 -  
385 -// @override  
386 -// Iterable<E> skip(int count) {  
387 -// return value.skip(count);  
388 -// }  
389 -  
390 -// @override  
391 -// Iterable<E> skipWhile(bool Function(E) test) {  
392 -// return value.skipWhile(test);  
393 -// }  
394 -  
395 -// @override  
396 -// Iterable<E> take(int count) {  
397 -// return value.take(count);  
398 -// }  
399 -  
400 -// @override  
401 -// Iterable<E> takeWhile(bool Function(E) test) {  
402 -// return value.takeWhile(test);  
403 -// }  
404 -  
405 -// @override  
406 -// List<E> toList({bool growable = true}) {  
407 -// return value.toList(growable: growable);  
408 -// }  
409 -  
410 -// @override  
411 -// Set<E> toSet() {  
412 -// return value.toSet();  
413 -// }  
414 -  
415 -// @override  
416 -// Iterable<E> where(bool Function(E) test) {  
417 -// return value.where(test);  
418 -// }  
419 -  
420 -// @override  
421 -// Iterable<T> whereType<T>() {  
422 -// return value.whereType<T>();  
423 -// }  
424 -  
425 -// @override  
426 -// bool containsAll(Iterable<Object> other) {  
427 -// return value.containsAll(other);  
428 -// }  
429 -  
430 -// @override  
431 -// Set<E> difference(Set<Object> other) {  
432 -// return value.difference(other);  
433 -// }  
434 -  
435 -// @override  
436 -// Set<E> intersection(Set<Object> other) {  
437 -// return value.intersection(other);  
438 -// }  
439 -  
440 -// @override  
441 -// E lookup(Object object) {  
442 -// return value.lookup(object);  
443 -// }  
444 -  
445 -// @override  
446 -// void removeAll(Iterable<Object> elements) {  
447 -// _value.removeAll(elements);  
448 -// refresh();  
449 -// }  
450 -  
451 -// @override  
452 -// void retainAll(Iterable<Object> elements) {  
453 -// _value.retainAll(elements);  
454 -// refresh();  
455 -// }  
456 -  
457 -// @override  
458 -// void retainWhere(bool Function(E) E) {  
459 -// _value.retainWhere(E);  
460 -// refresh();  
461 -// }  
462 -  
463 -// @override  
464 -// Set<E> union(Set<E> other) {  
465 -// return value.union(other);  
466 -// }  
467 -// }  
468 -  
469 extension SetExtension<E> on Set<E> { 144 extension SetExtension<E> on Set<E> {
470 RxSet<E> get obs { 145 RxSet<E> get obs {
471 if (this != null) { 146 if (this != null) {
1 name: get 1 name: get
2 description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with GetX. 2 description: Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with GetX.
3 -version: 3.16.1 3 +version: 3.16.2
4 homepage: https://github.com/jonataslaw/getx 4 homepage: https://github.com/jonataslaw/getx
5 5
6 environment: 6 environment:
@@ -163,17 +163,23 @@ GetValue is ${calculePercentage(dart, getx).round()}% more fast than Default Val @@ -163,17 +163,23 @@ GetValue is ${calculePercentage(dart, getx).round()}% more fast than Default Val
163 print(''' 163 print('''
164 GetStream is ${calculePercentage(dart, mini).round()}% more fast than Default Stream with $times listeners'''); 164 GetStream is ${calculePercentage(dart, mini).round()}% more fast than Default Stream with $times listeners''');
165 print('-----------'); 165 print('-----------');
  166 +
166 times = 30000; 167 times = 30000;
167 dart = await stream(); 168 dart = await stream();
168 getx = await getStream(); 169 getx = await getStream();
169 mini = await miniStream(); 170 mini = await miniStream();
  171 +
  172 + times = 60000;
  173 + dart = await stream();
  174 + getx = await getStream();
  175 + mini = await miniStream();
170 print('-----------'); 176 print('-----------');
171 print('dart_stream delay $dart ms to made $times requests'); 177 print('dart_stream delay $dart ms to made $times requests');
172 print('getx_stream delay $getx ms to made $times requests'); 178 print('getx_stream delay $getx ms to made $times requests');
173 print('getx_mini_stream delay $mini ms to made $times requests'); 179 print('getx_mini_stream delay $mini ms to made $times requests');
174 print('-----------'); 180 print('-----------');
175 print(''' 181 print('''
176 -GetStream is ${calculePercentage(dart, getx).round()}% more fast than Default Stream with $times listeners'''); 182 +GetStream is ${calculePercentage(dart, mini).round()}% more fast than Default Stream with $times listeners''');
177 }); 183 });
178 } 184 }
179 185