fast_rx 0.1.3 fast_rx: ^0.1.3 copied to clipboard
An easy to understand reactive state management solution for Flutter
fast_rx is a reactive state management solution for Flutter
Inspired by GetX, observable_ish, and similar packages
Features #
Class | Use-case |
---|---|
FastBuilder | Rebuilds when reactive values within change |
RxValue | A reactive value |
RxObject | A reactive object |
RxList | A reactive list |
RxMap | A reactive map |
RxSet | A reactive set |
There are convenience typedefs for RxBool, RxInt, RxDouble, and RxString
Usage #
import 'package:fast_rx/fast_rx.dart';
import 'package:flutter/material.dart';
void example() {
// ...
final count = 0.rx;
// ...
// ignore: avoid_print
count.stream.listen(print);
// ...
FastBuilder(() => Text('$count'));
FastBuilder(
() => Text('$count'),
condition: () => true,
);
// ...
// Will print the value and trigger a rebuild of FastBuilders
count.value = 1;
}
Custom RxObjects #
RxObject can be used to create reactive objects of classes outside of your control. If an object is within your control, consider making fields reactive instead.
import 'package:fast_rx/fast_rx.dart';
import 'package:flutter/material.dart';
class Tuple<T1, T2> {
T1 item1;
T2 item2;
Tuple(this.item1, this.item2);
Tuple.from(Tuple<T1, T2> other) : this(other.item1, other.item2);
@override
operator ==(Object other) =>
other is Tuple<T1, T2> && other.item1 == item1 && other.item2 == item2;
@override
int get hashCode => hashValues(item1, item2);
}
class RxTuple<T1, T2> extends RxObject<Tuple<T1, T2>> implements Tuple<T1, T2> {
RxTuple(Tuple<T1, T2> value) : super(value);
@override
T1 get item1 => value.item1;
@override
set item1(T1 value) => notifyIfChanged(() => unregisteredValue.item1 = value);
@override
T2 get item2 => value.item2;
@override
set item2(T2 value) => notifyIfChanged(() => unregisteredValue.item2 = value);
@override
Tuple<T1, T2> copyValue() => Tuple.from(unregisteredValue);
@override
bool shouldNotify(Tuple<T1, T2> oldValue) =>
oldValue.item1 != unregisteredValue.item1 ||
oldValue.item2 != unregisteredValue.item2;
}
extension RxTupleExtension<T1, T2> on Tuple<T1, T2> {
RxTuple<T1, T2> get rx => RxTuple<T1, T2>(this);
}
Testing custom RxObjects #
Custom RxObjects can be tested for valid registration and notifications
import 'package:fast_rx/fast_rx.dart';
import 'package:fast_rx/testing.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rx_tuple.dart';
void main() {
test('RxObject notifications', () {
final rx = Tuple(1, 2).rx;
expect(
rx.stream,
emitsInOrder(
[
Tuple(1, 2),
Tuple(2, 2),
Tuple(2, 3),
],
),
);
// Notify of the initial value
rx.notify();
// Update the value
rx.item1 = 2;
// Should not notify
rx.item2 = 2;
rx.item2 = 3;
// RxObject.value setter should throw if used
expect(
// ignore: invalid_use_of_protected_member
() => rx.value = Tuple(0, 0),
throwsA(isA<RxObjectValueIsReadOnly>()),
);
});
test('RxObject registration', () {
final rx = Tuple(1, 2).rx;
expectRxRegistration(
rx,
shouldRegister: [
() => rx.item1,
() => rx.item2,
],
shouldNotRegister: [
() => rx.item1 = 3,
() => rx.item2 = 3,
],
);
});
}
Additional information #
See fast_ui for more information