Skip to main content

flutterx_utils 2.0.0 copy "flutterx_utils: ^2.0.0" to clipboard
flutterx_utils: ^2.0.0 copied to clipboard

Flutter toolkit of typed extensions, JSON helpers, mutex and cancellation, tagged logging and layout widgets shared by the flutterx packages.

flutterx_utils #

Typed extensions, JSON helpers, mutex and cancellation, tagged logging and layout widgets for Flutter, shared by the flutterx packages. It only offers what the Flutter SDK does not.

Installation #

flutter pub add flutterx_utils
import 'package:flutterx_utils/flutterx_utils.dart';

JSON and maps #

Map reads values through three families: require* returns or throws, opt* returns null, get* returns a fallback. A key that is missing or null counts as absent; a value of the wrong type throws an ArgumentError naming the key.

class User with DTO {
  final String name;
  final int age;
  final Role role;
  final List<Tag> tags;

  User.fromJson(JsonObject json)
    : name = json.requireString('name'),
      age = json.getInt('age', fallback: 18),
      role = json.getEnum('role', Role.values, fallback: Role.guest),
      tags = json.getJsonList('tags', Tag.fromJson);

  @override
  JsonObject toJson() => {'name': name, 'age': age, 'role': role.name, 'tags': tags.toJsonList()};
}
  • Bool, Int and Double also accept strings ('true', '42'); Int rejects values with a fractional part. A malformed string throws a FormatException in require* and counts as absent in opt* and get*.
  • Enum reads by name, or by index with index: true, and ignoreCase: true ignores case. An unknown name, a missing key or an out-of-range index yields null in opt* and the fallback in get*; require* throws an ArgumentError naming the key.
  • MapEnum reads through a Map<String, E>, with lower: true to lowercase the input first.
  • requireJsonObject, requireJsonList, requireList and requireMap read nested data, each with opt*; the get* of lists and maps give an empty collection when absent.
  • getRaw<E> returns the value as-is; require<X, T> and opt<X, T> apply your own conversion.
  • DTO.toString() prints the fields from toJson() in debug builds and only Type(…) in release.
  • hashMap(map) hashes by content, independent of key order.
  • List<Enum> has requireFromName, fromName and optFromName.

Concurrency #

Mutex runs one async task at a time, waiters in arrival order:

final mutex = Mutex();
await mutex.lock(() async => save());

MutexRun throttles or debounces calls. A call that does not run gets its fallback: a value, a Future, or null for a nullable result; without one it fails with ConcurrentExecutionError. Any other fallback type throws an ArgumentError at once.

final search = MutexRun.last(const Duration(milliseconds: 300)); // debounce
final results = await search(() => api.search(text), fallback: null);

final submit = MutexRun.first(); // ignore taps while running
submit(() => api.send(form), fallback: null);
Factory Behaviour
MutexRun.once() Runs until the first success; later calls get the fallback until invalidate().
MutexRun.first() Throttle: runs only when nothing is running.
MutexRun.every(delay) Like first, plus the fallback within delay of the last completed run.
MutexRun.last(delay) Debounce: after delay only the latest call runs.

CancellationToken makes one attached future fail with CancelException when cancelled; CancellationToken.timeout(duration) cancels by itself. One task at a time per token.

final token = CancellationToken();
final data = token.attach(api.load());
token.cancel();

Logging #

Mix Loggable into a class or State. Everything is logged in debug builds and nothing in release; levels are set per type or tag.

class Repo with Loggable {
  void load() => logInfo('loading', () => logDebug('from cache'));
}

Loggable.setLevelFor<Repo>(LogLevel.warning);

logRun indents the nested messages; override logInternal to redirect the output.

Extensions #

On Members
Brightness isDark, negative
Color >>/<< lighten/darken (HSL), * sets the alpha, + paints over, blend, differenceRGB, negative, brightness, hexString, toHSLColor
Iterable interpolate, count, countWhere, distinctBy
List nextElement, updateWhere, updateAllWhere, upsertWhere
Set toggleAdd
String lowerCamelCase, upperCamelCase, snakeCase, capitalized, nonEmptyOrNull
any let

color * 0.5 replaces the alpha with 0.5; it does not halve the current one. TypedFactoryMap caches one item per key and requested type; asking for another type replaces the item.

Layout and scroll widgets #

SizeObserver reports its child size after the frame, only when it changes, so the callback may call setState:

SizeObserver(
  onSizeChanged: (size) => setState(() => _size = size),
  child: const Text('Hello'),
)

It measures with a dry layout by default; wrap a child that does not support it (such as an input decorator) in SafeDryLayout, or pass useDryLayout: false. constraints (PartialBoxConstraints) changes the measuring constraints.

ScrollableView scrolls its child in both directions and drives external controllers, so scrollbars attach to any content:

ScrollableViewScrollbar.both(
  controllerX: x,
  controllerY: y,
  child: ScrollableView(controllerX: x, controllerY: y, child: table),
)

onViewportSize and onChildSize are called after the frame. matchContainerX/Y stretches content smaller than the viewport.

WidgetDataSync keeps data derived from a widget in sync across rebuilds (sync() in didUpdateWidget, dispose() in dispose). schedulePostFrame runs a callback after the frame if called during build, immediately otherwise; scheduleEndOfFrame always waits for the frame end.

Claude Code plugin #

The repository ships a plugin with skills that teach Claude Code to integrate the library:

/plugin marketplace add https://gitlab.com/dade.sliep/flutterx_utils
/plugin install flutterx-utils@flutterx-utils
2
likes
150
points
453
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter toolkit of typed extensions, JSON helpers, mutex and cancellation, tagged logging and layout widgets shared by the flutterx packages.

Repository (GitLab)
View/report issues

License

BSD-3-Clause (license)

Dependencies

clock, flutter, vector_math

More

Packages that depend on flutterx_utils