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