Add a Reactive "Rx-type" holder that triggers the listeners when it receives the same value
Showing
2 changed files
with
75 additions
and
0 deletions
@@ -379,6 +379,30 @@ class Rx<T> extends _RxImpl<T> { | @@ -379,6 +379,30 @@ class Rx<T> extends _RxImpl<T> { | ||
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
382 | +/// Similar class to Rx<T> but this also will refresh the listeners if the same | ||
383 | +/// value has been provided. This is useful when maintaining a state with the | ||
384 | +/// same user = User("foo"). | ||
385 | +/// For example, supposed we have a `int seconds = 2` and we want to animate | ||
386 | +/// from invisible to visible a widget in two seconds: | ||
387 | +/// RxEvent<int>.call(seconds); | ||
388 | +/// then after a click happens, you want to call a RxEvent<int>.call(seconds). | ||
389 | +/// This will refresh the listener of an AnimatedWidget and will keep the value | ||
390 | +/// if the Rx is kept in memory. | ||
391 | +/// | ||
392 | +class RxEvent<T> extends Rx<T> { | ||
393 | + RxEvent([T initial]) : super(initial); | ||
394 | + | ||
395 | + void trigger([T v]) { | ||
396 | + var firstRebuild = this.firstRebuild; | ||
397 | + value = v; | ||
398 | + // If it's not the first rebuild, the listeners have been called already | ||
399 | + // So we won't call them again. | ||
400 | + if (!firstRebuild) { | ||
401 | + subject.add(v); | ||
402 | + } | ||
403 | + } | ||
404 | +} | ||
405 | + | ||
382 | extension StringExtension on String { | 406 | extension StringExtension on String { |
383 | /// Returns a `RxString` with [this] `String` as initial value. | 407 | /// Returns a `RxString` with [this] `String` as initial value. |
384 | RxString get obs => RxString(this); | 408 | RxString get obs => RxString(this); |
@@ -95,4 +95,55 @@ void main() { | @@ -95,4 +95,55 @@ void main() { | ||
95 | await Future.delayed(Duration.zero); | 95 | await Future.delayed(Duration.zero); |
96 | expect(count, 555); | 96 | expect(count, 555); |
97 | }); | 97 | }); |
98 | + | ||
99 | + test('Rx same value will not call the same listener', () async { | ||
100 | + var reactiveInteger = RxInt(2); | ||
101 | + var timesCalled = 0; | ||
102 | + reactiveInteger.listen((newInt) { | ||
103 | + timesCalled++; | ||
104 | + }); | ||
105 | + | ||
106 | + // we call 3 | ||
107 | + reactiveInteger.call(3); | ||
108 | + // then repeat twice | ||
109 | + reactiveInteger.call(3); | ||
110 | + reactiveInteger.call(3); | ||
111 | + | ||
112 | + await Future.delayed(Duration(milliseconds: 100)); | ||
113 | + expect(1, timesCalled); | ||
114 | + }); | ||
115 | + | ||
116 | + test('RxEvent same value will trigger the listener when trigger', () async { | ||
117 | + var reactiveInteger = RxEvent<int>(2); | ||
118 | + var timesCalled = 0; | ||
119 | + reactiveInteger.listen((newInt) { | ||
120 | + timesCalled++; | ||
121 | + }); | ||
122 | + | ||
123 | + // we call 3 | ||
124 | + reactiveInteger.trigger(3); | ||
125 | + // then repeat twice | ||
126 | + reactiveInteger.trigger(3); | ||
127 | + reactiveInteger.trigger(3); | ||
128 | + | ||
129 | + await Future.delayed(Duration(milliseconds: 100)); | ||
130 | + expect(3, timesCalled); | ||
131 | + }); | ||
132 | + | ||
133 | + test('RxEvent same value will not trigger the listener when call', () async { | ||
134 | + var reactiveInteger = RxEvent<int>(2); | ||
135 | + var timesCalled = 0; | ||
136 | + reactiveInteger.listen((newInt) { | ||
137 | + timesCalled++; | ||
138 | + }); | ||
139 | + | ||
140 | + // we call 3 | ||
141 | + reactiveInteger.call(3); | ||
142 | + // then repeat twice | ||
143 | + reactiveInteger.call(3); | ||
144 | + reactiveInteger.call(3); | ||
145 | + | ||
146 | + await Future.delayed(Duration(milliseconds: 100)); | ||
147 | + expect(1, timesCalled); | ||
148 | + }); | ||
98 | } | 149 | } |
-
Please register or login to post a comment