Represents a mutable reactive state container that sits at the foundation of the reactivity system.
Signals hold a single, mutable value that can be read or modified. When a signal's value is updated, any active computations (like Computed) or effects (like effect) that read the signal's value inside their execution context are automatically notified and scheduled to re-run.
Under the hood, this establishes a reactive dependency graph where reading a signal registers the reader as a "target", and updating a signal triggers direct, glitch-free propagation to all registered targets.
.value inside a reactive context (like effect or computed) registers a dependency. Reading a value
outside a reactive context behaves like a standard getter without creating a subscription.
Example Usage#
1. Basic Reactive Flow
import 'package:preact_signals/preact_signals.dart';
void main() {
final count = Signal(0);
// The effect automatically subscribes to count.value
effect(() {
print('Count is: ${count.value}');
});
count.value = 5; // Triggers print: Count is: 5
}
2. Controlling Subscriptions via .peek()
If you need to read a signal's value without subscribing to updates, use the .peek() method:
final count = Signal(0);
final threshold = Signal(10);
effect(() {
// Subscribes to count, but NOT to threshold
if (count.value >= threshold.peek()) {
print('Threshold reached!');
}
});
Constructors#
View Constructors
Signal(this._internalValue, {String? name, void Function()? watched, void Function()? unwatched, ReadonlySignalOptions? options, SignalEquality? equality})
Creates a new Signal instance with the given initial value.
You can optionally provide:
- A name for debugging/observer tracing.
- watched/unwatched hooks triggered when the signal gains its first subscriber or loses its last subscriber.
- equality checking callback to customize how value modifications are compared.
final count = Signal(0, name: 'counter_signal');
Signal.lazy({String? name, void Function()? watched, void Function()? unwatched, ReadonlySignalOptions? options, SignalEquality? equality})
Creates a new lazy Signal instance that is computed on-demand upon first read.
.value = ... or .set(...)
will throw a runtime initialization exception.
final lazyUser = Signal<User>.lazy(name: 'lazy_user');
// Throws error:
// print(lazyUser.value);
lazyUser.value = User(id: 1, name: 'John'); // Initialized successfully
print(lazyUser.value); // Safe to read now
Properties#
View Properties
int globalId
String? name
void Function()? watched
void Function()? unwatched
int version
Version numbers should always be >= 0, because the special value -1 is used by Nodes to signify potentially unused but recyclable nodes.
Methods#
View Methods
SignalEquality equalityCheck
Get the active equality check
bool isInitialized
Check if the value is set and not a lazy signal
T internalValue
bool internalRefresh()
void subscribeToNode(Node node)
void unsubscribeFromNode(Node node)
void Function() subscribe(void Function(T value) fn)
T value
Gets the current value of the signal.
If read inside an active reactive context (e.g., an effect or computed signal), the calling context automatically subscribes to updates of this signal.
value(T val)
Sets the current value of the signal.
If the new value is not equal to the existing value (based on equalityCheck), the signal's version is incremented and all active downstream subscribers (computeds/effects) are synchronously notified to re-evaluate.
bool set(T val, {bool force = false})
Updates the signal's value by method call.
Under normal conditions, this only notifies subscribers if the new value is different from the current value.
Set force to true to bypass standard equality checks and notify downstream subscribers
unconditionally. This is useful when working with mutable collections or class instances where
properties change in-place but the object reference remains identical.
final numbers = Signal([1, 2, 3]);
numbers.value.add(4); // In-place modification
numbers.set(numbers.value, force: true); // Force notify downstream subscribers
ReadonlySignalOptions#
Configuration options for a ReadonlySignal.
Allows intercepting the signal's active subscription state changes via watched and unwatched callback event listeners. This is extremely useful for initiating or canceling active background fetching, web sockets, or timer loops.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final stockTicker = signal(
0.0,
options: ReadonlySignalOptions(
name: 'stock-ticker',
watched: () => print('Stock Ticker is actively being listened to!'),
unwatched: () => print('No more listeners, sleeping the ticker.'),
),
);
Constructors#
View Constructors
ReadonlySignalOptions({super.name, this.watched, this.unwatched})
Creates a new ReadonlySignalOptions instance.
Properties#
View Properties
void Function()? watched
Callback called when the signal goes from 0 to >=1 listeners.
void Function()? unwatched
Callback called when the signal goes from >=1 to 0 listeners.
Methods#
View Methods
ReadonlySignalOptions copyWith({String? name, void Function()? watched, void Function()? unwatched})
Creates a copy of this options with custom overrides.
bool ==(Object other)
int hashCode
SetSignalExtension#
Helper extensions for [Signal<Set
Under the hood, these methods mutate the underlying set and call set(..., force: true) to trigger all listeners and computations.
import 'package:signals_core/signals_core.dart';
final tags = <String>{}.$;
effect(() {
print('Tags: ${tags.value}');
});
tags.add('dart'); // Automatically prints: Tags: {dart}
tags.addAll(['flutter', 'signals']); // Automatically prints: Tags: {dart, flutter, signals}
Methods#
View Methods
bool add(E value)
void addAll(Iterable elements)
void clear()
bool remove(Object? value)
void removeAll(Iterable<Object?> elements)
void removeWhere(bool Function(E element) test)
void retainAll(Iterable<Object?> elements)
void retainWhere(bool Function(E element) test)
ComputedOptions#
Configuration options for a Computed signal.
Enables configuring debugging names and subscription state event listeners for computed derivations.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final count = signal(0);
final doubleCount = computed(
() => count.value * 2,
options: ComputedOptions(
name: 'double-count',
watched: () => print('Computed doubleCount is active'),
unwatched: () => print('Computed doubleCount is inactive'),
),
);
Constructors#
View Constructors
ComputedOptions({super.name, super.watched, super.unwatched})
Creates a new ComputedOptions instance.
Methods#
View Methods
ComputedOptions copyWith({String? name, void Function()? watched, void Function()? unwatched})
bool ==(Object other)
int hashCode
SignalOptions#
Configuration options for a Signal.
Extends ReadonlySignalOptions to also support custom equality checkers, which control whether incoming values trigger update events.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final items = signal(
[1, 2, 3],
options: SignalOptions(
name: 'item-list',
equality: SignalEquality.deep(),
watched: () => print('Items watch active'),
unwatched: () => print('Items watch inactive'),
),
);
Constructors#
View Constructors
SignalOptions({super.name, super.watched, super.unwatched, SignalEquality? equality})
Creates a new SignalOptions instance.
Methods#
View Methods
SignalEquality equalityCheck
Get the active equality check
SignalOptions copyWith({String? name, void Function()? watched, void Function()? unwatched})
bool ==(Object other)
int hashCode
EffectOptions#
Configuration options for reactive Effects.
Permits naming the effect for debugging, performance profiling, and tracing within the signals developer tools.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final count = signal(0);
final logger = effect(
() => print('Count changed to: ${count.value}'),
options: const EffectOptions(name: 'counter-logger'),
);
Constructors#
Methods#
View Methods
EffectOptions copyWith({String? name})
Creates a copy of this options with custom overrides.
bool ==(Object other)
int hashCode
BoolSignalExtension#
Helper extensions for ReadonlySignal
import 'package:signals_core/signals_core.dart';
final a = true.$;
final b = false.$;
final andResult = a & b.value; // false
final orResult = a | b.value; // true
Methods#
View Methods
bool &(bool other)
The logical conjunction ("and") of this and other.
Returns true if both this and other are true, and false otherwise.
bool |(bool other)
The logical disjunction ("inclusive or") of this and other.
Returns true if either this or other is true, and false otherwise.
bool ^(bool other)
The logical exclusive disjunction ("exclusive or") of this and other.
Returns whether this and other are neither both true nor both false.
NumSignalExtension#
Helper extensions for ReadonlySignal.value.
import 'package:signals_core/signals_core.dart';
final a = 5.0.$;
final sum = a + 3; // 8.0 (evaluates reactively)
final isGreater = a > 4; // true
Methods#
View Methods
num +(num other)
Adds other to this number.
The result is an int, as described by [int.+], if both this number and other is an integer, otherwise the result is a double.
num -(num other)
Subtracts other from this number.
The result is an int, as described by int.-, if both this number and other is an integer, otherwise the result is a double.
num *(num other)
Multiplies this number by other.
The result is an int, as described by [int.*], if both this number and other are integers, otherwise the result is a double.
num %(num other)
Euclidean modulo of this number by other.
Returns the remainder of the Euclidean division.
The Euclidean division of two integers a and b
yields two integers q and r such that
a == b * q + r and 0 <= r < b.abs().
The Euclidean division is only defined for integers, but can be easily
extended to work with doubles. In that case, q is still an integer,
but r may have a non-integer value that still satisfies 0 <= r < |b|.
The sign of the returned value r is always positive.
See remainder for the remainder of the truncating division.
The result is an int, as described by [int.%], if both this number and other are integers, otherwise the result is a double.
Example:
print(5 % 3); // 2
print(-5 % 3); // 1
print(5 % -3); // 2
print(-5 % -3); // 1
double /(num other)
Divides this number by other.
int ~/(num other)
Truncating division operator.
Performs truncating division of this number by other. Truncating division is division where a fractional result is converted to an integer by rounding towards zero.
If both operands are ints, then other must not be zero.
Then a ~/ b corresponds to a.remainder(b)
such that a == (a ~/ b) * b + a.remainder(b).
If either operand is a double, then the other operand is converted
to a double before performing the division and truncation of the result.
Then a ~/ b is equivalent to (a / b).truncate().
This means that the intermediate result of the double division
must be a finite integer (not an infinity or double.nan).
num -()
The negation of this value.
The negation of a number is a number of the same kind
(int or double) representing the negation of the
numbers numerical value (the result of subtracting the
number from zero), if that value exists.
Negating a double gives a number with the same magnitude
as the original value (number.abs() == (-number).abs()),
and the opposite sign (-(number.sign) == (-number).sign).
Negating an integer, -number, is equivalent to subtracting
it from zero, 0 - number.
(Both properties generally also hold for the other type, but with a few edge case exceptions).
num remainder(num other)
The remainder of the truncating division of this by other.
The result r of this operation satisfies:
this == (this ~/ other) * other + r.
As a consequence, the remainder r has the same sign as the dividend
this.
The result is an int, as described by int.remainder, if both this number and other are integers, otherwise the result is a double.
Example:
print(5.remainder(3)); // 2
print(-5.remainder(3)); // -2
print(5.remainder(-3)); // 2
print(-5.remainder(-3)); // -2
bool <(num other)
Whether this number is numerically smaller than other.
Returns true if this number is smaller than other.
Returns false if this number is greater than or equal to other
or if either value is a NaN value like double.nan.
bool <=(num other)
Whether this number is numerically smaller than or equal to other.
Returns true if this number is smaller than or equal to other.
Returns false if this number is greater than other
or if either value is a NaN value like double.nan.
bool >(num other)
Whether this number is numerically greater than other.
Returns true if this number is greater than other.
Returns false if this number is smaller than or equal to other
or if either value is a NaN value like double.nan.
bool >=(num other)
Whether this number is numerically greater than or equal to other.
Returns true if this number is greater than or equal to other.
Returns false if this number is smaller than other
or if either value is a NaN value like double.nan.
bool isNaN
Whether this number is a Not-a-Number value.
Is true if this number is the double.nan value
or any other of the possible double NaN values.
Is false if this number is an integer,
a finite double or an infinite double (double.infinity
or double.negativeInfinity).
All numbers satisfy exactly one of isInfinite, isFinite
and isNaN.
bool isNegative
Whether this number is negative.
A number is negative if it's smaller than zero,
or if it is the double -0.0.
This precludes a NaN value like double.nan from being negative.
bool isInfinite
Whether this number is positive infinity or negative infinity.
Only satisfied by double.infinity and double.negativeInfinity.
All numbers satisfy exactly one of isInfinite, isFinite
and isNaN.
bool isFinite
Whether this number is finite.
The only non-finite numbers are NaN values, positive infinity, and negative infinity. All integers are finite.
All numbers satisfy exactly one of isInfinite, isFinite
and isNaN.
num abs()
The absolute value of this number.
The absolute value is the value itself, if the value is non-negative,
and -value if the value is negative.
Integer overflow may cause the result of -value to stay negative.
print((2).abs()); // 2
print((-2.5).abs()); // 2.5
num sign
Negative one, zero or positive one depending on the sign and numerical value of this number.
The value minus one if this number is less than zero, plus one if this number is greater than zero, and zero if this number is equal to zero.
Returns NaN if this number is a double NaN value.
Returns a number of the same type as this number.
For doubles, (-0.0).sign is -0.0.
The result satisfies:
n == n.sign * n.abs()
for all numbers n (except NaN, because NaN isn't == to itself).
int round()
The integer closest to this number.
Rounds away from zero when there is no closest integer:
(3.5).round() == 4 and (-3.5).round() == -4.
The number must be finite (see isFinite).
If the value is greater than the highest representable positive integer, the result is that highest positive integer. If the value is smaller than the highest representable negative integer, the result is that highest negative integer.
int floor()
The greatest integer no greater than this number.
Rounds fractional values towards negative infinity.
The number must be finite (see isFinite).
If the value is greater than the highest representable positive integer, the result is that highest positive integer. If the value is smaller than the highest representable negative integer, the result is that highest negative integer.
int ceil()
The least integer no smaller than this.
Rounds fractional values towards positive infinity.
The number must be finite (see isFinite).
If the value is greater than the highest representable positive integer, the result is that highest positive integer. If the value is smaller than the highest representable negative integer, the result is that highest negative integer.
int truncate()
The integer obtained by discarding any fractional digits from this.
Rounds fractional values towards zero.
The number must be finite (see isFinite).
If the value is greater than the highest representable positive integer, the result is that highest positive integer. If the value is smaller than the highest representable negative integer, the result is that highest negative integer.
double roundToDouble()
The double integer value closest to this value.
Rounds away from zero when there is no closest integer:
(3.5).roundToDouble() == 4 and (-3.5).roundToDouble() == -4.
If this is already an integer valued double, including -0.0, or it is a
non-finite double value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0,
and -0.0 is therefore considered closer to negative numbers than 0.0.
This means that for a value d in the range -0.5 < d < 0.0,
the result is -0.0.
double floorToDouble()
Returns the greatest double integer value no greater than this.
If this is already an integer valued double, including -0.0, or it is a
non-finite double value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0.
A number d in the range 0.0 < d < 1.0 will return 0.0.
double ceilToDouble()
Returns the least double integer value no smaller than this.
If this is already an integer valued double, including -0.0, or it is a
non-finite double value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0.
A number d in the range -1.0 < d < 0.0 will return -0.0.
double truncateToDouble()
Returns the double integer value obtained by discarding any fractional
digits from the double value of this.
If this is already an integer valued double, including -0.0, or it is a
non-finite double value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0.
A number d in the range -1.0 < d < 0.0 will return -0.0, and
in the range 0.0 < d < 1.0 it will return 0.0.
num clamp(num lowerLimit, num upperLimit)
Returns this num clamped to be in the range lowerLimit-upperLimit.
The comparison is done using compareTo and therefore takes -0.0 into
account. This also implies that double.nan is treated as the maximal
double value.
The arguments lowerLimit and upperLimit must form a valid range where
lowerLimit.compareTo(upperLimit) <= 0.
Example:
var result = 10.5.clamp(5, 10.0); // 10.0
result = 0.75.clamp(5, 10.0); // 5
result = (-10).clamp(-5, 5.0); // -5
result = (-0.0).clamp(-5, 5.0); // -0.0
int toInt()
Truncates this num to an integer and returns the result as an int.
Equivalent to truncate.
double toDouble()
This number as a double.
If an integer number is not precisely representable as a double, an approximation is returned.
String toStringAsFixed(int fractionDigits)
A decimal-point string-representation of this number.
Converts this number to a double before computing the string representation, as by toDouble.
If the absolute value of this is greater than or equal to 10^21, then
this methods returns an exponential representation computed by
this.toStringAsExponential(). Otherwise the result
is the closest string representation with exactly fractionDigits digits
after the decimal point. If fractionDigits equals 0, then the decimal
point is omitted.
The parameter fractionDigits must be an integer satisfying:
0 <= fractionDigits <= 20.
Examples:
1.toStringAsFixed(3); // 1.000
(4321.12345678).toStringAsFixed(3); // 4321.123
(4321.12345678).toStringAsFixed(5); // 4321.12346
123456789012345.toStringAsFixed(3); // 123456789012345.000
10000000000000000.toStringAsFixed(4); // 10000000000000000.0000
5.25.toStringAsFixed(0); // 5
String toStringAsExponential([int? fractionDigits])
An exponential string-representation of this number.
Converts this number to a double before computing the string representation.
If fractionDigits is given, then it must be an integer satisfying:
0 <= fractionDigits <= 20. In this case the string contains exactly
fractionDigits after the decimal point. Otherwise, without the parameter,
the returned string uses the shortest number of digits that accurately
represent this number.
If fractionDigits equals 0, then the decimal point is omitted. Examples:
1.toStringAsExponential(); // 1e+0
1.toStringAsExponential(3); // 1.000e+0
123456.toStringAsExponential(); // 1.23456e+5
123456.toStringAsExponential(3); // 1.235e+5
123.toStringAsExponential(0); // 1e+2
String toStringAsPrecision(int precision)
A string representation with precision significant digits.
Converts this number to a double and returns a string representation of that value with exactly precision significant digits.
The parameter precision must be an integer satisfying:
1 <= precision <= 21.
Examples:
1.toStringAsPrecision(2); // 1.0
1e15.toStringAsPrecision(3); // 1.00e+15
1234567.toStringAsPrecision(3); // 1.23e+6
1234567.toStringAsPrecision(9); // 1234567.00
12345678901234567890.toStringAsPrecision(20); // 12345678901234567168
12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19
0.00000012345.toStringAsPrecision(15); // 1.23450000000000e-7
0.0000012345.toStringAsPrecision(15); // 0.00000123450000000000
DoubleSignalExtension#
Helper extensions for ReadonlySignal
import 'package:signals_core/signals_core.dart';
final doubleSignal = 2.5.$;
final rounded = doubleSignal.round(); // 3
final negated = -doubleSignal; // -2.5
Methods#
View Methods
double remainder(num other)
Returns the remainder of this value divided by other.
double +(num other)
Returns the sum of this value and other.
double -(num other)
Returns the difference of this value and other.
double *(num other)
Returns the product of this value and other.
double %(num other)
Returns the modulo of this value and other.
double /(num other)
Returns the division of this value and other.
int ~/(num other)
Returns the truncating division of this value and other.
double -()
Returns the negation of this value.
double abs()
Returns the absolute value of this value.
double sign
The sign of the double's numerical value.
Returns -1.0 if the value is less than zero, +1.0 if the value is greater than zero, and the value itself if it is -0.0, 0.0 or NaN.
int round()
Returns the integer closest to this number.
Rounds away from zero when there is no closest integer:
(3.5).round() == 4 and (-3.5).round() == -4.
Throws an UnsupportedError if this number is not finite (NaN or an infinity).
print(3.0.round()); // 3
print(3.25.round()); // 3
print(3.5.round()); // 4
print(3.75.round()); // 4
print((-3.5).round()); // -4
int floor()
Returns the greatest integer no greater than this number.
Rounds the number towards negative infinity.
Throws an UnsupportedError if this number is not finite (NaN or infinity).
print(1.99999.floor()); // 1
print(2.0.floor()); // 2
print(2.99999.floor()); // 2
print((-1.99999).floor()); // -2
print((-2.0).floor()); // -2
print((-2.00001).floor()); // -3
int ceil()
Returns the least integer that is not smaller than this number.
Rounds the number towards infinity.
Throws an UnsupportedError if this number is not finite (NaN or an infinity).
print(1.99999.ceil()); // 2
print(2.0.ceil()); // 2
print(2.00001.ceil()); // 3
print((-1.99999).ceil()); // -1
print((-2.0).ceil()); // -2
print((-2.00001).ceil()); // -2
int truncate()
Returns the integer obtained by discarding any fractional part of this number.
Rounds the number towards zero.
Throws an UnsupportedError if this number is not finite (NaN or an infinity).
print(2.00001.truncate()); // 2
print(1.99999.truncate()); // 1
print(0.5.truncate()); // 0
print((-0.5).truncate()); // 0
print((-1.5).truncate()); // -1
print((-2.5).truncate()); // -2
double roundToDouble()
Returns the integer double value closest to this.
Rounds away from zero when there is no closest integer:
(3.5).roundToDouble() == 4 and (-3.5).roundToDouble() == -4.
If this is already an integer valued double, including -0.0, or it is not
a finite value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0,
and -0.0 is therefore considered closer to negative numbers than 0.0.
This means that for a value d in the range -0.5 < d < 0.0,
the result is -0.0.
print(3.0.roundToDouble()); // 3.0
print(3.25.roundToDouble()); // 3.0
print(3.5.roundToDouble()); // 4.0
print(3.75.roundToDouble()); // 4.0
print((-3.5).roundToDouble()); // -4.0
double floorToDouble()
Returns the greatest integer double value no greater than this.
If this is already an integer valued double, including -0.0, or it is not
a finite value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0.
A number d in the range 0.0 < d < 1.0 will return 0.0.
print(1.99999.floorToDouble()); // 1.0
print(2.0.floorToDouble()); // 2.0
print(2.99999.floorToDouble()); // 2.0
print((-1.99999).floorToDouble()); // -2.0
print((-2.0).floorToDouble()); // -2.0
print((-2.00001).floorToDouble()); // -3.0
double ceilToDouble()
Returns the least integer double value no smaller than this.
If this is already an integer valued double, including -0.0, or it is not
a finite value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0.
A number d in the range -1.0 < d < 0.0 will return -0.0.
print(1.99999.ceilToDouble()); // 2.0
print(2.0.ceilToDouble()); // 2.0
print(2.00001.ceilToDouble()); // 3.0
print((-1.99999).ceilToDouble()); // -1.0
print((-2.0).ceilToDouble()); // -2.0
print((-2.00001).ceilToDouble()); // -2.0
double truncateToDouble()
Returns the integer double value obtained by discarding any fractional
digits from this.
If this is already an integer valued double, including -0.0, or it is not
a finite value, the value is returned unmodified.
For the purpose of rounding, -0.0 is considered to be below 0.0.
A number d in the range -1.0 < d < 0.0 will return -0.0, and
in the range 0.0 < d < 1.0 it will return 0.0.
print(2.5.truncateToDouble()); // 2.0
print(2.00001.truncateToDouble()); // 2.0
print(1.99999.truncateToDouble()); // 1.0
print(0.5.truncateToDouble()); // 0.0
print((-0.5).truncateToDouble()); // -0.0
print((-1.5).truncateToDouble()); // -1.0
print((-2.5).truncateToDouble()); // -2.0
ReadonlySetSignalExtension#
Helper extensions for [ReadonlySignal<Set
import 'package:signals_core/signals_core.dart';
final setA = {1, 2, 3}.$;
final setB = {3, 4, 5}.$;
final diff = computed(() => setA.difference(setB.value)); // {1, 2}
Methods#
View Methods
Set cast()
bool containsAll(Iterable<Object?> other)
Set difference(Set<Object?> other)
Set intersection(Set<Object?> other)
E? lookup(Object? object)
Set union(Set other)
SignalStreamUtils#
Extension on Stream to provide convenient utilities to convert streams into reactive signals.
import 'package:signals_core/signals_core.dart';
final myStream = Stream.periodic(Duration(seconds: 1), (x) => x).take(5);
final mySignal = myStream.toStreamSignal();
Methods#
View Methods
StreamSignal toStreamSignal({bool? cancelOnError, T? initialValue, bool lazy = true, List<ReadonlySignal> dependencies = const [], void Function()? onDone, AsyncSignalOptions? options})
Convert a stream to a signal
import 'package:signals/signals.dart';
Stream<int> createStream() async* {
yield 1;
yield 2;
yield 3;
}
final stream = createStream();
final signal = stream.toSignal();
For returning a signal with the value that can be accessed sync use stream.toSyncSignal instead.
ReadonlySignal toSyncSignal(T initialData)
Convert a Stream to a synchronous ReadonlySignal and provide an initial value.
This is different from toStreamSignal() because it directly feeds the stream's values
into a standard Signal, allowing you to read the bare, synchronous values directly
instead of wrapping them in an AsyncState.
import 'package:signals_core/signals_core.dart';
final stream = Stream.value(42);
final syncSignal = stream.toSyncSignal(0);
print(syncSignal.value); // 0 (initially)
// After the stream emits:
// print(syncSignal.value); // 42
signal#
Convenient global constructor for creating a mutable reactive state signal.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final count = signal(0);
final name = signal('Jane');
lazySignal#
Lazy signal that can be created with type T that the value will be assigned later.
final db = lazySignal<DatabaseConnection>();
...
db.value = DatabaseConnect(...);
SignalOptionsBase#
Base configuration options for reactive components and signals.
Contains common options across all signals, computed values, and effects, such as the debug name.
Constructors#
Properties#
Methods#
ReadonlySignalUtils#
Utility extensions on ReadonlySignal to bridge reactive programming with asynchronous streams and select sub-states.
Methods#
View Methods
Stream toStream()
Convert a signal to a Stream to be consumed as a read only stream.
Computed select(R Function(ReadonlySignal) selector, [ComputedOptions? options])
Select a sub-state value from this signal and return a computed signal that only notifies when that specific sub-state changes.
This is highly useful for nesting or destructuring complex objects or maps without triggering downstream updates on changes to unrelated fields.
import 'package:signals_core/signals_core.dart';
final user = signal({'name': 'John', 'age': 30});
final name = user.select((val) => val()['name'] as String);
effect(() => print('Name changed: ${name.value}'));
// Unrelated field update: does NOT trigger the name effect!
user.value = {'name': 'John', 'age': 31};
// Related field update: triggers the name effect!
user.value = {'name': 'Jane', 'age': 31};
WriteableSignalUtils#
Utility extensions on Signal providing functional programming wrappers like React-style hooks destructuring.
Methods#
View Methods
(T Function(), void Function(T)) hooks
Easy destructure to get and set the value
final counter = signal(0);
...
final (getCount, setCount) = counter.hooks;
SignalFunctionExtensions#
Utility extension on a getter function T Function() to instantly convert it into a Computed
signal.
Methods#
View Methods
Computed $
Return a cached, derived Computed
import 'package:signals_core/signals_core.dart';
final count = signal(0);
final doubleCount = (() => count.value * 2).$;
print(doubleCount.value); // 0
count.value = 5;
print(doubleCount.value); // 10
EffectCycleDetectionError#
Cycle detection usually means you have updated a signal inside an effect and are reading by value.
SignalDoubleExtensions#
Utility extension on double to easily lift a double into a reactive Signal.
Methods#
View Methods
Signal $
Lift a primitive double into a reactive Signal
import 'package:signals_core/signals_core.dart';
final doubleSignal = 3.14.$;
print(doubleSignal.value); // 3.14
SignalBoolExtensions#
Utility extension on bool to easily lift a boolean into a reactive Signal.
Methods#
View Methods
Signal $
Lift a primitive bool into a reactive Signal
import 'package:signals_core/signals_core.dart';
final isEnabled = true.$;
print(isEnabled.value); // true
SignalIterableUtils#
Utility extension methods on Iterable to convert them to IterableSignals.
Methods#
View Methods
IterableSignal toSignal({IterableSignalOptions? options, @Deprecated('Use options: IterableSignalOptions(autoDispose: ...) instead') bool? autoDispose, @Deprecated('Use options: IterableSignalOptions(name: ...) instead') String? debugLabel})
Convert an existing Iterable to an IterableSignal.
This returns an IterableSignal initialized with the current collection.
import 'package:signals/signals.dart';
final numbers = [1, 2, 3];
final signal = numbers.toSignal();
SignalNumExtensions#
Utility extension on num to easily lift a number into a reactive Signal.
Methods#
View Methods
Signal $
Lift a primitive num into a reactive Signal
import 'package:signals_core/signals_core.dart';
final counter = 10.$;
print(counter.value); // 10
SignalSetExtensions#
Utility extension on Set to easily lift a set into a reactive Signal.
Methods#
View Methods
Signal<Set> $
Lift a primitive Set into a reactive [Signal<Set
import 'package:signals_core/signals_core.dart';
final tags = {'sports', 'news'}.$;
print(tags.value); // {'sports', 'news'}
SignalListUtils#
Utility extension methods on List to convert them to ListSignals.
Methods#
View Methods
ListSignal toSignal({ListSignalOptions? options, @Deprecated('Use options: ListSignalOptions(autoDispose: ...) instead') bool? autoDispose, @Deprecated('Use options: ListSignalOptions(name: ...) instead') String? debugLabel})
Convert this existing List to a reactive ListSignal.
import 'package:signals/signals.dart';
final myList = [1, 2, 3];
final signal = myList.toSignal();
SignalMapUtils#
Utility extension methods on Map to convert them to MapSignals.
Methods#
View Methods
MapSignal<K, V> toSignal({MapSignalOptions<K, V>? options, @Deprecated('Use options: MapSignalOptions(autoDispose: ...) instead') bool? autoDispose, @Deprecated('Use options: MapSignalOptions(name: ...) instead') String? debugLabel})
Convert this existing Map to a reactive MapSignal.
import 'package:signals/signals.dart';
final myMap = {'key': 'value'};
final signal = myMap.toSignal();
SignalSetUtils#
Utility extension methods on Set to convert them to SetSignals.
Methods#
View Methods
SetSignal toSignal({SetSignalOptions? options, @Deprecated('Use options: SetSignalOptions(autoDispose: ...) instead') bool? autoDispose, @Deprecated('Use options: SetSignalOptions(name: ...) instead') String? debugLabel})
Convert this existing Set to a reactive SetSignal.
import 'package:signals/signals.dart';
final mySet = {1, 2, 3};
final signal = mySet.toSignal();
SignalsWriteAfterDisposeError#
Error to throw if a signal is written to after it is disposed
Constructors#
View Constructors
SignalsWriteAfterDisposeError(ReadonlySignal instance)
Error to throw if a signal is written to after it is disposed
SignalFutureUtils#
Extension on future to provide helpful methods for signals
Methods#
View Methods
FutureSignal toFutureSignal({Duration? timeout, T? initialValue, bool lazy = true, List<ReadonlySignal> dependencies = const [], AsyncSignalOptions? options})
Convert an existing future to FutureSignal
import 'package:signals/signals.dart';
final future = Future(() => 1);
final signal = future.toSignal();
ReadonlySignalMixin#
Readonly signal mixin for adding addition helper methods
Methods#
View Methods
bool isInitialized
Check if a signal value is set (does not subscribe)
String? debugLabel
Debug label for Debug Mode Debug label for Debug Mode
T value
T peek()
SignalsReadAfterDisposeError#
Error to throw if a signal is read after it is disposed
Constructors#
View Constructors
SignalsReadAfterDisposeError(ReadonlySignal instance)
Error to throw if a signal is read after it is disposed
ComparableSignalExtension#
Helper extensions for [ReadonlySignal<Comparable
Methods#
View Methods
int compareTo(T other)
Compares this object to another object.
Returns a value like a Comparator when comparing this to other.
That is, it returns a negative integer if this is ordered before other,
a positive integer if this is ordered after other,
and zero if this and other are ordered together.
The other argument must be a value that is comparable to this object.
LazySignalInitializationError#
Lazy signal must value value set before it is read
Constructors#
View Constructors
LazySignalInitializationError(ReadonlySignal instance)
Lazy signal must value value set before it is read
SignalEffectException#
Error for when a effect fails to run the callback
Constructors#
View Constructors
SignalEffectException(this.error, [this.stackTrace])
Error for when a effect fails to run the callback
Properties#
View Properties
Object? error
Error during callback
StackTrace? stackTrace
StackTrace for where the error started
Methods#
ReadonlyIterableSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
bool any(bool Function(E element) test)
Iterable cast()
bool contains(Object? value)
E elementAt(int index)
bool every(bool Function(E element) test)
Iterable expand(Iterable Function(E element) toElements)
E first
E firstWhere(bool Function(E element) test, {E Function()? orElse})
R fold(R initialValue, R Function(R previousValue, E element) combine)
Iterable followedBy(Iterable other)
bool isEmpty
bool isNotEmpty
Iterator iterator
String join([String separator = ""])
E last
E lastWhere(bool Function(E element) test, {E Function()? orElse})
int length
Iterable map(R Function(E e) toElement)
E reduce(E Function(E value, E element) combine)
E single
E singleWhere(bool Function(E element) test, {E Function()? orElse})
Iterable skip(int count)
Iterable skipWhile(bool Function(E value) test)
Iterable take(int count)
Iterable takeWhile(bool Function(E value) test)
List toList({bool growable = true})
Set toSet()
Iterable where(bool Function(E element) test)
Iterable whereType()
void forEach(void Function(E element) action)
ChangeSignalOptions#
Configuration options for a ChangeStackSignal.
Constructors#
View Constructors
ChangeSignalOptions({this.limit, super.name, super.autoDispose, super.watched, super.unwatched})
Creates a new ChangeSignalOptions instance.
Properties#
Methods#
View Methods
ChangeSignalOptions copyWith({int? limit, String? name, bool? autoDispose, void Function()? watched, void Function()? unwatched})
bool ==(Object other)
int hashCode
PatternSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
Iterable allMatches(String string, [int start = 0])
Matches this pattern against the string repeatedly.
If start is provided, matching will start at that index.
The returned iterable lazily finds non-overlapping matches of the pattern in the string. If a user only requests the first match, this function should not compute all possible matches.
The matches are found by repeatedly finding the first match of the pattern in the string, initially starting from start, and then from the end of the previous match (but always at least one position later than the start of the previous match, in case the pattern matches an empty substring).
RegExp exp = RegExp(r'(\w+)');
var str = 'Dash is a bird';
Iterable<Match> matches = exp.allMatches(str, 8);
for (final Match m in matches) {
String match = m[0]!;
print(match);
}
The output of the example is:
a
bird
Match? matchAsPrefix(String string, [int start = 0])
Matches this pattern against the start of string.
Returns a match if the pattern matches a substring of string
starting at start, and null if the pattern doesn't match
at that point.
The start must be non-negative and no greater than string.length.
final string = 'Dash is a bird';
var regExp = RegExp(r'bird');
var match = regExp.matchAsPrefix(string, 10); // Match found.
regExp = RegExp(r'bird');
match = regExp.matchAsPrefix(string); // null
StringSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
String [](int index)
The character (as a single-code-unit String) at the given index.
The returned string represents exactly one UTF-16 code unit, which may be half of a surrogate pair. A single member of a surrogate pair is an invalid UTF-16 string:
var clef = '\u{1D11E}';
// These represent invalid UTF-16 strings.
clef[0].codeUnits; // [0xD834]
clef[1].codeUnits; // [0xDD1E]
This method is equivalent to
String.fromCharCode(this.codeUnitAt(index)).
int codeUnitAt(int index)
Returns the 16-bit UTF-16 code unit at the given index.
int length
The length of the string.
Returns the number of UTF-16 code units in this string. The number of runes might be fewer if the string contains characters outside the Basic Multilingual Plane (plane 0):
'Dart'.length; // 4
'Dart'.runes.length; // 4
var clef = '\u{1D11E}';
clef.length; // 2
clef.runes.length; // 1
bool endsWith(String other)
Whether this string ends with other.
For example:
const string = 'Dart is open source';
print(string.endsWith('urce')); // true
bool startsWith(Pattern pattern, [int index = 0])
Whether this string starts with a match of pattern.
const string = 'Dart is open source';
print(string.startsWith('Dar')); // true
print(string.startsWith(RegExp(r'[A-Z][a-z]'))); // true
If index is provided, this method checks if the substring starting at that index starts with a match of pattern:
const string = 'Dart';
print(string.startsWith('art', 0)); // false
print(string.startsWith('art', 1)); // true
print(string.startsWith(RegExp(r'\w{3}'), 2)); // false
index must not be negative or greater than length.
A RegExp containing '^' does not match if the index is greater than zero and the regexp is not multi-line. The pattern works on the string as a whole, and does not extract a substring starting at index first:
const string = 'Dart';
print(string.startsWith(RegExp(r'^art'), 1)); // false
print(string.startsWith(RegExp(r'art'), 1)); // true
int indexOf(Pattern pattern, [int start = 0])
Returns the position of the first match of pattern in this string, starting at start, inclusive:
const string = 'Dartisans';
print(string.indexOf('art')); // 1
print(string.indexOf(RegExp(r'[A-Z][a-z]'))); // 0
Returns -1 if no match is found:
const string = 'Dartisans';
string.indexOf(RegExp(r'dart')); // -1
The start must be non-negative and not greater than length.
int lastIndexOf(Pattern pattern, [int? start])
The starting position of the last match pattern in this string.
Finds a match of pattern by searching backward starting at start:
const string = 'Dartisans';
print(string.lastIndexOf('a')); // 6
print(string.lastIndexOf(RegExp(r'a(r|n)'))); // 6
Returns -1 if pattern could not be found in this string.
const string = 'Dartisans';
print(string.lastIndexOf(RegExp(r'DART'))); // -1
If start is omitted, search starts from the end of the string. If supplied, start must be non-negative and not greater than length.
bool isEmpty
Whether this string is empty.
bool isNotEmpty
Whether this string is not empty.
String +(String other)
Creates a new string by concatenating this string with other.
Example:
const string = 'dart' + 'lang'; // 'dartlang'
String substring(int start, [int? end])
The substring of this string from start, inclusive, to end, exclusive.
Example:
const string = 'dartlang';
var result = string.substring(1); // 'artlang'
result = string.substring(1, 4); // 'art'
Both start and end must be non-negative and no greater than length; end, if provided, must be greater than or equal to start.
String trim()
The string without any leading and trailing whitespace.
If the string contains leading or trailing whitespace, a new string with no leading and no trailing whitespace is returned:
final trimmed = '\tDart is fun\n'.trim();
print(trimmed); // 'Dart is fun'
Otherwise, the original string itself is returned:
const string1 = 'Dart';
final string2 = string1.trim(); // 'Dart'
print(identical(string1, string2)); // true
Whitespace is defined by the Unicode White_Space property (as defined in version 6.2 or later) and the BOM character, 0xFEFF.
Here is the list of trimmed characters according to Unicode version 6.3:
0009..000D ; White_Space # Cc <control-0009>..<control-000D>
0020 ; White_Space # Zs SPACE
0085 ; White_Space # Cc <control-0085>
00A0 ; White_Space # Zs NO-BREAK SPACE
1680 ; White_Space # Zs OGHAM SPACE MARK
2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE
2028 ; White_Space # Zl LINE SEPARATOR
2029 ; White_Space # Zp PARAGRAPH SEPARATOR
202F ; White_Space # Zs NARROW NO-BREAK SPACE
205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE
3000 ; White_Space # Zs IDEOGRAPHIC SPACE
FEFF ; BOM ZERO WIDTH NO_BREAK SPACE
Some later versions of Unicode do not include U+0085 as a whitespace character. Whether it is trimmed depends on the Unicode version used by the system.
String trimLeft()
The string without any leading whitespace.
As trim, but only removes leading whitespace.
final string = ' Dart '.trimLeft();
print(string); // 'Dart '
String trimRight()
The string without any trailing whitespace.
As trim, but only removes trailing whitespace.
final string = ' Dart '.trimRight();
print(string); // ' Dart'
String *(int times)
Creates a new string by concatenating this string with itself a number of times.
The result of str * n is equivalent to
str + str + ...(n times)... + str.
const string = 'Dart';
final multiplied = string * 3;
print(multiplied); // 'DartDartDart'
Returns an empty string if times is zero or negative.
String padLeft(int width, [String padding = ' '])
Pads this string on the left if it is shorter than width.
Returns a new string that prepends padding onto this string one time for each position the length is less than width.
const string = 'D';
print(string.padLeft(4)); // ' D'
print(string.padLeft(2, 'x')); // 'xD'
print(string.padLeft(4, 'y')); // 'yyyD'
print(string.padLeft(4, '>>')); // '>>>>>>D'
If width is already smaller than or equal to this.length,
no padding is added. A negative width is treated as zero.
If padding has length different from 1, the result will not
have length width. This may be useful for cases where the
padding is a longer string representing a single character, like
" " or "\u{10002}".
In that case, the user should make sure that this.length is
the correct measure of the string's length.
String padRight(int width, [String padding = ' '])
Pads this string on the right if it is shorter than width.
Returns a new string that appends padding after this string one time for each position the length is less than width.
const string = 'D';
print(string.padRight(4)); // 'D '
print(string.padRight(2, 'x')); // 'Dx'
print(string.padRight(4, 'y')); // 'Dyyy'
print(string.padRight(4, '>>')); // 'D>>>>>>'
If width is already smaller than or equal to this.length,
no padding is added. A negative width is treated as zero.
If padding has length different from 1, the result will not
have length width. This may be useful for cases where the
padding is a longer string representing a single character, like
" " or "\u{10002}".
In that case, the user should make sure that this.length is
the correct measure of the string's length.
bool contains(Pattern other, [int startIndex = 0])
Whether this string contains a match of other.
Example:
const string = 'Dart strings';
final containsD = string.contains('D'); // true
final containsUpperCase = string.contains(RegExp(r'[A-Z]')); // true
If startIndex is provided, this method matches only at or after that index:
const string = 'Dart strings';
final containsD = string.contains(RegExp('D'), 0); // true
final caseSensitive = string.contains(RegExp(r'[A-Z]'), 1); // false
The startIndex must not be negative or greater than length.
String replaceFirst(Pattern from, String to, [int startIndex = 0])
Creates a new string with the first occurrence of from replaced by to.
Finds the first match of from in this string, starting from startIndex, and creates a new string where that match is replaced with the to string.
Example:
'0.0001'.replaceFirst(RegExp(r'0'), ''); // '.0001'
'0.0001'.replaceFirst(RegExp(r'0'), '7', 1); // '0.7001'
String replaceFirstMapped(Pattern from, String Function(Match match) replace, [int startIndex = 0])
Replace the first occurrence of from in this string.
const string = 'Dart is fun';
print(string.replaceFirstMapped(
'fun', (m) => 'open source')); // Dart is open source
print(string.replaceFirstMapped(
RegExp(r'\w(\w*)'), (m) => '<${m[0]}-${m[1]}>')); // <Dart-art> is fun
Returns a new string, which is this string except that the first match of from, starting from startIndex, is replaced by the result of calling replace with the match object.
The startIndex must be non-negative and no greater than length.
String replaceAll(Pattern from, String replace)
Replaces all substrings that match from with replace.
Creates a new string in which the non-overlapping substrings matching
from (the ones iterated by from.allMatches(thisString)) are replaced
by the literal string replace.
'resume'.replaceAll(RegExp(r'e'), 'é'); // 'résumé'
Notice that the replace string is not interpreted. If the replacement depends on the match (for example, on a RegExp's capture groups), use the replaceAllMapped method instead.
String replaceAllMapped(Pattern from, String Function(Match match) replace)
Replace all substrings that match from by a computed string.
Creates a new string in which the non-overlapping substrings that match
from (the ones iterated by from.allMatches(thisString)) are replaced
by the result of calling replace on the corresponding Match object.
This can be used to replace matches with new content that depends on the match, unlike replaceAll where the replacement string is always the same.
The replace function is called with the Match generated by the pattern, and its result is used as replacement.
The function defined below converts each word in a string to simplified 'pig latin' using replaceAllMapped:
String pigLatin(String words) => words.replaceAllMapped(
RegExp(r'\b(\w*?)([aeiou]\w*)', caseSensitive: false),
(Match m) => "${m[2]}${m[1]}${m[1]!.isEmpty ? 'way' : 'ay'}");
final result = pigLatin('I have a secret now!');
print(result); // 'Iway avehay away ecretsay ownay!'
String replaceRange(int start, int? end, String replacement)
Replaces the substring from start to end with replacement.
Creates a new string equivalent to:
this.substring(0, start) + replacement + this.substring(end)
Example:
const string = 'Dart is fun';
final result = string.replaceRange(8, null, 'open source');
print(result); // Dart is open source
The start and end indices must specify a valid range of this string.
That is 0 <= start <= end <= this.length.
If end is null, it defaults to length.
List split(Pattern pattern)
Splits the string at matches of pattern and returns a list of substrings.
Finds all the matches of pattern in this string,
as by using Pattern.allMatches,
and returns the list of the substrings between the matches,
before the first match, and after the last match.
const string = 'Hello world!';
final splitted = string.split(' ');
print(splitted); // [Hello, world!];
If the pattern doesn't match this string at all, the result is always a list containing only the original string.
If the pattern is a String, then it's always the case that:
string.split(pattern).join(pattern) == string
If the first match is an empty match at the start of the string, the empty substring before it is not included in the result. If the last match is an empty match at the end of the string, the empty substring after it is not included in the result. If a match is empty, and it immediately follows a previous match (it starts at the position where the previous match ended), then the empty substring between the two matches is not included in the result.
const string = 'abba';
final re = RegExp(r'b*');
// re.allMatches(string) will find four matches:
// * empty match before first "a".
// * match of "bb"
// * empty match after "bb", before second "a"
// * empty match after second "a".
print(string.split(re)); // [a, a]
A non-empty match at the start or end of the string, or after another match, is not treated specially, and will introduce empty substrings in the result:
const string = 'abbaa';
final splitted = string.split('a'); // ['', 'bb', '', '']
If this string is the empty string, the result is an empty list
if pattern matches the empty string, since the empty string
before and after the first-and-last empty match are not included.
(It is still a list containing the original empty string [""]
if the pattern doesn't match).
const string = '';
print(string.split('')); // []
print(string.split('a')); // []
Splitting with an empty pattern splits the string into single-code unit strings.
const string = 'Pub';
print(string.split('')); // [P, u, b]
// Same as:
var codeUnitStrings = [
for (final unit in string.codeUnits) String.fromCharCode(unit)
];
print(codeUnitStrings); // [P, u, b]
Splitting happens at UTF-16 code unit boundaries, and not at rune (Unicode code point) boundaries:
// String made up of two code units, but one rune.
const string = '\u{1D11E}';
final splitted = string.split('');
print(splitted); // ['\ud834', '\udd1e'] - 2 unpaired surrogate values
To get a list of strings containing the individual runes of a string, you should not use split. You can instead get a string for each rune as follows:
const string = '\u{1F642}';
for (final rune in string.runes) {
print(String.fromCharCode(rune));
}
String splitMapJoin(Pattern pattern, {String Function(Match)? onMatch, String Function(String)? onNonMatch})
Splits the string, converts its parts, and combines them into a new string.
The pattern is used to split the string into parts and separating matches. Each match of Pattern.allMatches of pattern on this string is used as a match, and the substrings between the end of one match (or the start of the string) and the start of the next match (or the end of the string) is treated as a non-matched part. (There is no omission of leading or trailing empty matchs, like in split, all matches and parts between the are included.)
Each match is converted to a string by calling onMatch. If onMatch is omitted, the matched substring is used.
Each non-matched part is converted to a string by a call to onNonMatch. If onNonMatch is omitted, the non-matching substring itself is used.
Then all the converted parts are concatenated into the resulting string.
final result = 'Eats shoots leaves'.splitMapJoin(RegExp(r'shoots'),
onMatch: (m) => '${m[0]}', // (or no onMatch at all)
onNonMatch: (n) => '*');
print(result); // *shoots*
List codeUnits
An unmodifiable list of the UTF-16 code units of this string.
Runes runes
An Iterable of Unicode code-points of this string.
If the string contains surrogate pairs, they are combined and returned as one integer by this iterator. Unmatched surrogate halves are treated like valid 16-bit code-units.
String toLowerCase()
Converts all characters in this string to lower case.
If the string is already in all lower case, this method returns this.
'ALPHABET'.toLowerCase(); // 'alphabet'
'abc'.toLowerCase(); // 'abc'
This function uses the language independent Unicode mapping and thus only works in some languages.
String toUpperCase()
Converts all characters in this string to upper case.
If the string is already in all upper case, this method returns this.
'alphabet'.toUpperCase(); // 'ALPHABET'
'ABC'.toUpperCase(); // 'ABC'
This function uses the language independent Unicode mapping and thus only works in some languages.
IterableSignalOptions#
Configuration options for a IterableSignal.
Constructors#
View Constructors
IterableSignalOptions({super.name, super.autoDispose, super.watched, super.unwatched, super.equality = const SignalDeepEquality()})
Creates a new IterableSignalOptions instance.
Methods#
View Methods
IterableSignalOptions copyWith({String? name, bool? autoDispose, void Function()? watched, void Function()? unwatched, SignalEquality<Iterable>? equality})
bool ==(Object other)
int hashCode
EnumSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
int index
A numeric identifier for the enumerated value.
The values of a single enumeration are numbered
consecutively from zero to one less than the
number of values.
This is also the index of the value in the
enumerated type's static values list.
String name
The name of the enum value.
The name is a string containing the source identifier used to declare the enum value.
For example, given a declaration like:
enum MyEnum {
value1,
value2
}
the result of MyEnum.value1.name is the string "value1".
ReadonlyListSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
List cast()
E last
List +(List other)
E [](int index)
Map<int, E> asMap()
Iterable expand(Iterable Function(E element) toElements)
E firstWhere(bool Function(E element) test, {E Function()? orElse})
R fold(R initialValue, R Function(R previousValue, E element) combine)
Iterable followedBy(Iterable other)
Iterable getRange(int start, int end)
int indexOf(E element, [int start = 0])
int indexWhere(bool Function(E element) test, [int start = 0])
int lastIndexOf(E element, [int? start])
int lastIndexWhere(bool Function(E element) test, [int? start])
Iterable reversed
List sorted([int Function(E a, E b)? compare])
Return a new array that is sorted by the compare function
List sublist(int start, [int? end])
IntSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
int &(int other)
Bit-wise and operator.
Treating both this and other as sufficiently large two's component
integers, the result is a number with only the bits set that are set in
both this and other
If both operands are negative, the result is negative, otherwise the result is non-negative.
print((2 & 1).toRadixString(2)); // 0010 & 0001 -> 0000
print((3 & 1).toRadixString(2)); // 0011 & 0001 -> 0001
print((10 & 2).toRadixString(2)); // 1010 & 0010 -> 0010
int |(int other)
Bit-wise or operator.
Treating both this and other as sufficiently large two's component
integers, the result is a number with the bits set that are set in either
of this and other
If both operands are non-negative, the result is non-negative, otherwise the result is negative.
Example:
print((2 | 1).toRadixString(2)); // 0010 | 0001 -> 0011
print((3 | 1).toRadixString(2)); // 0011 | 0001 -> 0011
print((10 | 2).toRadixString(2)); // 1010 | 0010 -> 1010
int ^(int other)
Bit-wise exclusive-or operator.
Treating both this and other as sufficiently large two's component
integers, the result is a number with the bits set that are set in one,
but not both, of this and other
If the operands have the same sign, the result is non-negative, otherwise the result is negative.
Example:
print((2 ^ 1).toRadixString(2)); // 0010 ^ 0001 -> 0011
print((3 ^ 1).toRadixString(2)); // 0011 ^ 0001 -> 0010
print((10 ^ 2).toRadixString(2)); // 1010 ^ 0010 -> 1000
int ~()
The bit-wise negate operator.
Treating this as a sufficiently large two's component integer,
the result is a number with the opposite bits set.
This maps any integer x to -x - 1.
int <<(int shiftAmount)
Shift the bits of this integer to the left by shiftAmount.
Shifting to the left makes the number larger, effectively multiplying
the number by pow(2, shiftAmount).
There is no limit on the size of the result. It may be relevant to limit intermediate values by using the "and" operator with a suitable mask.
It is an error if shiftAmount is negative.
Example:
print((3 << 1).toRadixString(2)); // 0011 -> 0110
print((9 << 2).toRadixString(2)); // 1001 -> 100100
print((10 << 3).toRadixString(2)); // 1010 -> 1010000
int >>(int shiftAmount)
Shift the bits of this integer to the right by shiftAmount.
Shifting to the right makes the number smaller and drops the least
significant bits, effectively doing an integer division by
pow(2, shiftAmount).
It is an error if shiftAmount is negative.
Example:
print((3 >> 1).toRadixString(2)); // 0011 -> 0001
print((9 >> 2).toRadixString(2)); // 1001 -> 0010
print((10 >> 3).toRadixString(2)); // 1010 -> 0001
print((-6 >> 2).toRadixString); // 111...1010 -> 111...1110 == -2
print((-85 >> 3).toRadixString); // 111...10101011 -> 111...11110101 == -11
int >>>(int shiftAmount)
Bitwise unsigned right shift by shiftAmount bits.
The least significant shiftAmount bits are dropped, the remaining bits (if any) are shifted down, and zero-bits are shifted in as the new most significant bits.
The shiftAmount must be non-negative.
Example:
print((3 >>> 1).toRadixString(2)); // 0011 -> 0001
print((9 >>> 2).toRadixString(2)); // 1001 -> 0010
print(((-9) >>> 2).toRadixString(2)); // 111...1011 -> 001...1110 (> 0)
int modPow(int exponent, int modulus)
Returns this integer to the power of exponent modulo modulus.
The exponent must be non-negative and modulus must be positive.
int modInverse(int modulus)
Returns the modular multiplicative inverse of this integer modulo modulus.
The modulus must be positive.
It is an error if no modular inverse exists.
int gcd(int other)
Returns the greatest common divisor of this integer and other.
If either number is non-zero, the result is the numerically greatest
integer dividing both this and other.
The greatest common divisor is independent of the order,
so x.gcd(y) is always the same as y.gcd(x).
For any integer x, x.gcd(x) is x.abs().
If both this and other is zero, the result is also zero.
Example:
print(4.gcd(2)); // 2
print(8.gcd(4)); // 4
print(10.gcd(12)); // 2
print(10.gcd(0)); // 10
print((-2).gcd(-3)); // 1
bool isEven
Returns true if and only if this integer is even.
bool isOdd
Returns true if and only if this integer is odd.
int bitLength
Returns the minimum number of bits required to store this integer.
The number of bits excludes the sign bit, which gives the natural length for non-negative (unsigned) values. Negative values are complemented to return the bit position of the first bit that differs from the sign bit.
To find the number of bits needed to store the value as a signed value,
add one, i.e. use x.bitLength + 1.
x.bitLength == (-x-1).bitLength;
3.bitLength == 2; // 00000011
2.bitLength == 2; // 00000010
1.bitLength == 1; // 00000001
0.bitLength == 0; // 00000000
(-1).bitLength == 0; // 11111111
(-2).bitLength == 1; // 11111110
(-3).bitLength == 2; // 11111101
(-4).bitLength == 2; // 11111100
int toUnsigned(int width)
Returns the least significant width bits of this integer as a non-negative number (i.e. unsigned representation). The returned value has zeros in all bit positions higher than width.
(-1).toUnsigned(5) == 31 // 11111111 -> 00011111
This operation can be used to simulate arithmetic from low level languages. For example, to increment an 8 bit quantity:
q = (q + 1).toUnsigned(8);
q will count from 0 up to 255 and then wrap around to 0.
If the input fits in width bits without truncation, the result is the
same as the input. The minimum width needed to avoid truncation of x is
given by x.bitLength, i.e.
x == x.toUnsigned(x.bitLength);
int toSigned(int width)
Returns the least significant width bits of this integer, extending the highest retained bit to the sign. This is the same as truncating the value to fit in width bits using an signed 2-s complement representation. The returned value has the same bit value in all positions higher than width.
// V--sign bit-V
16.toSigned(5) == -16; // 00010000 -> 11110000
239.toSigned(5) == 15; // 11101111 -> 00001111
// ^ ^
This operation can be used to simulate arithmetic from low level languages. For example, to increment an 8 bit signed quantity:
q = (q + 1).toSigned(8);
q will count from 0 up to 127, wrap to -128 and count back up to
127.
If the input value fits in width bits without truncation, the result is
the same as the input. The minimum width needed to avoid truncation of x
is x.bitLength + 1, i.e.
x == x.toSigned(x.bitLength + 1);
int -()
Return the negative value of this integer.
The result of negating an integer always has the opposite sign, except for zero, which is its own negation.
int abs()
Returns the absolute value of this integer.
For any integer value,
the result is the same as value < 0 ? -value : value.
Integer overflow may cause the result of -value to stay negative.
int sign
Returns the sign of this integer.
Returns 0 for zero, -1 for values less than zero and +1 for values greater than zero.
int round()
Returns this.
int floor()
Returns this.
int ceil()
Returns this.
int truncate()
Returns this.
double roundToDouble()
Returns this.toDouble().
double floorToDouble()
Returns this.toDouble().
double ceilToDouble()
Returns this.toDouble().
double truncateToDouble()
Returns this.toDouble().
String toRadixString(int radix)
Converts this int to a string representation in the given radix.
In the string representation, lower-case letters are used for digits above '9', with 'a' being 10 and 'z' being 35.
The radix argument must be an integer in the range 2 to 36.
Example:
// Binary (base 2).
print(12.toRadixString(2)); // 1100
print(31.toRadixString(2)); // 11111
print(2021.toRadixString(2)); // 11111100101
print((-12).toRadixString(2)); // -1100
// Octal (base 8).
print(12.toRadixString(8)); // 14
print(31.toRadixString(8)); // 37
print(2021.toRadixString(8)); // 3745
// Hexadecimal (base 16).
print(12.toRadixString(16)); // c
print(31.toRadixString(16)); // 1f
print(2021.toRadixString(16)); // 7e5
// Base 36.
print((35 * 36 + 1).toRadixString(36)); // z1
ReadonlyMapSignalExtension#
Helper extensions for ReadonlySignal
Methods#
View Methods
V? [](Object? key)
Map<RK, RV> cast()
bool containsKey(Object? key)
bool containsValue(Object? value)
Iterable<MapEntry<K, V>> entries
bool isEmpty
bool isNotEmpty
Iterable keys
int length
Map<K2, V2> map(MapEntry<K2, V2> Function(K key, V value) convert)
Iterable values
ListSignalOptions#
Configuration options for a ListSignal.
Constructors#
View Constructors
ListSignalOptions({super.name, super.autoDispose, super.watched, super.unwatched, super.equality = const SignalDeepEquality()})
Creates a new ListSignalOptions instance.
Methods#
View Methods
ListSignalOptions copyWith({String? name, bool? autoDispose, void Function()? watched, void Function()? unwatched, SignalEquality<List>? equality})
bool ==(Object other)
int hashCode
MapSignalOptions#
Configuration options for a MapSignal.
Constructors#
View Constructors
MapSignalOptions({super.name, super.autoDispose, super.watched, super.unwatched, super.equality = const SignalDeepEquality()})
Creates a new MapSignalOptions instance.
Methods#
View Methods
MapSignalOptions<K, V> copyWith({String? name, bool? autoDispose, void Function()? watched, void Function()? unwatched, SignalEquality<Map<K, V>>? equality})
bool ==(Object other)
int hashCode
SetSignalOptions#
Configuration options for a SetSignal.
Constructors#
View Constructors
SetSignalOptions({super.name, super.autoDispose, super.watched, super.unwatched, super.equality = const SignalDeepEquality()})
Creates a new SetSignalOptions instance.
Methods#
View Methods
SetSignalOptions copyWith({String? name, bool? autoDispose, void Function()? watched, void Function()? unwatched, SignalEquality<Set>? equality})
bool ==(Object other)
int hashCode
SignalsAutoDisposeMixin#
Mixin to enable autodispose on a signal
Properties#
View Properties
bool autoDispose
Throws and error if read after dispose and can be disposed on last unsubscribe.
Methods#
View Methods
bool disposed
Check if the effect is disposed
void Function() onDispose(void Function() cleanup)
Add a cleanup function to be called when the signal is disposed
final counter = signal(0);
final effectCount = signal(0);
final cleanup = counter.onDispose(() {
print('Counter has been disposed');
});
// Remove the cleanup function
cleanup();
disposed(bool value)
Force a signal to be disposed
void dispose()
Dispose the signal
LinkedSignalOptions#
Options for creating a LinkedSignal.
Constructors#
View Constructors
LinkedSignalOptions({this.computation, this.sourceEquality, super.name, super.autoDispose})
Creates LinkedSignalOptions.
Properties#
View Properties
T Function(S source, LinkedSignalPreviousState<T, S>? previous)? computation
Custom computation logic that runs when the source changes.
bool Function(S a, S b)? sourceEquality
Optional equality check for the source values.
Methods#
View Methods
LinkedSignalOptions<T, S> copyWith({String? name, bool? autoDispose, void Function()? watched, void Function()? unwatched, T Function(S source, LinkedSignalPreviousState<T, S>? previous)? computation, bool Function(S a, S b)? sourceEquality})
bool ==(Object other)
int hashCode
ListSignalExtension#
Helper extensions for Signal
Methods#
View Methods
first(E val)
last(E val)
length(int value)
void []=(int index, E value)
void add(E value)
void addAll(Iterable iterable)
void clear()
void fillRange(int start, int end, [E? fillValue])
void insert(int index, E element)
void insertAll(int index, Iterable iterable)
bool remove(Object? value)
E removeAt(int index)
E removeLast()
void removeRange(int start, int end)
void removeWhere(bool Function(E element) test)
void replaceRange(int start, int end, Iterable replacements)
void retainWhere(bool Function(E element) test)
void setAll(int index, Iterable iterable)
void setRange(int start, int end, Iterable iterable, [int skipCount = 0])
void shuffle([Random? random])
void sort([int Function(E a, E b)? compare])
MapSignalExtension#
Helper extensions for Signal
Methods#
View Methods
void []=(K key, V value)
void addAll(Map<K, V> other)
void addEntries(Iterable<MapEntry<K, V>> newEntries)
void clear()
void forEach(void Function(K key, V value) action)
V putIfAbsent(K key, V Function() ifAbsent)
V? remove(Object? key)
void removeWhere(bool Function(K key, V value) test)
V update(K key, V Function(V value) update, {V Function()? ifAbsent})
void updateAll(V Function(K key, V value) update)
SignalObjectUtils#
Connivent methods for signal values
Methods#
SignalComparableExtensions#
Extensions for Comparable
Methods#
SignalIterableExtensions#
Extensions for Iterable
Methods#
SignalListExtensions#
Extensions for List
Methods#
SignalPatternExtensions#
Extensions for Pattern
Methods#
SignalMapExtensions#
Extensions for Map
Methods#
SignalStringExtensions#
Extensions for String
Methods#
SignalEnumExtensions#
Extensions for Enum
Methods#
SignalIntExtensions#
Extensions for int
Methods#
SignalsError#
Signal usage error