sint 2.0.2
sint: ^2.0.2 copied to clipboard
SINT (State, Injection, Navigation, Translation) - The Four Pillars of High-Fidelity Flutter Infrastructure.
SINT #
State · Injection · Navigation · Translation
High-performance, Clean Architecture micro-framework for Flutter.
The Four Pillars #
SINT focuses strictly on four foundational pillars—no HTTP client, validators, or unrelated bloat:
| Pillar | Core APIs | Guide |
|---|---|---|
| S — State | SintController, Obx, .obs, Sint.computed, Sint.batch, Sint.untrack, everSync |
State Docs |
| I — Injection | Sint.put, Sint.lazyPut, Sint.putAsync, Sint.find, Bind, SmartManagement |
Injection Docs |
| N — Navigation | SintApp, SintPage, SintRouterOutlet, Sint.toNamed, Sint.back, pathParams, queryParams |
Navigation Docs |
| T — Translation | .tr, .trParams, Translations, Sint.updateLocale, Sint.loadTranslations, translateEndpoints |
Translation Docs |
What's New in 2.0.0 #
- Standalone Design Systems (
SintApp): First-class host for Flutter 3.47+ standalonematerial_uiandcupertino_uipackages (Flutter >=3.44.0 / Dart >=3.12.0), while preservingSintMaterialAppandSintCupertinoAppfor SDK Material/Cupertino apps. See MIGRATION_DESIGN_SYSTEMS.md. - State-of-the-Art Signals Engine (
Obx$O(1)$ +batch+computed+untrack): Brings the modern fine-grained Signals triad (inspired by SolidJS, Preact Signals, and Angular Signals) to Flutter—persistent $O(1)$Obxlistener diffing with automatic conditional-branch pruning, zero-allocationSint.batch, memoizedSint.computed,Sint.untrack/rx.peek, and controller-scopedeverSync/autoDispose. - Multi-Level Prefix Trie Router: Indexes all leading literal route segments and reuses compiled
PathDecodedtemplates (97.8× faster on 1,000 shared-prefix routes:250.48 µs → 2.56 µs/op). - Nested Routing (
SintRouterOutlet): Declarative nested outlets andIndexedRouteBuildersynchronized with imperativeNavigatorcalls.
Quick Start #
dependencies:
sint: ^2.0.0
import 'package:flutter/widgets.dart';
import 'package:material_ui/material_ui.dart';
import 'package:sint/sint.dart';
class CartController extends SintController {
final items = 1.obs;
final price = 25.obs;
late final total = computed(() => items.value * price.value); // Auto-disposed on route close
void addBundle() => Sint.batch(() {
items.value += 2;
price.value = 20;
});
}
void main() => runApp(
SintApp(
materialTheme: ThemeData(),
initialRoute: '/',
sintPages: [
SintPage(
name: '/',
binds: [Bind.put(CartController())],
page: () {
final c = Sint.find<CartController>();
return Scaffold(
body: Center(child: Obx(() => Text('Total: \$${c.total.value}'))),
floatingActionButton: FloatingActionButton(
onPressed: c.addBundle,
child: const Text('+'),
),
);
},
),
],
),
);
Architectural Positioning & 4-Pillar Benchmark #
Why SINT 2.0 is Not GetX (And Why Context-Free is Clean Architecture) #
GetX was criticized for bundling unrelated utilities (GetConnect HTTP/sockets, string validators), using Type.toString() keys that broke under Web/Wasm minification, leaking conditional Obx listeners, and lacking batching or computed signals. SINT 2.0 replaces those internals with:
- Strict 4-Pillar Scope (
S · I · N · T): Clean Architecture boundaries (domain,engine,router,ui) with zero unrelated utilities. - Reified
Type-Keyed DI & $O(M)$ Route Teardown: Safe under Web/Wasm minification; route-owned controllers andcomputedsignals auto-dispose deterministically when their route exits. - Zero-Stream Synchronous Signals:
StreamControlleris allocated lazily only if.stream/.listenis called;Obx,Computed,Sint.batch, andeverSyncrun on synchronous pointer lists. - Why Context-Free APIs (
Sint.toNamed,Sint.find,.tr) Are Safe by Design: In Flutter, navigation, snackbars, and localization belong to the root application host (NavigatorState/ScaffoldMessengerState), not to leaf widgets. ThreadingBuildContextinto controllers or async callbacks couples domain logic to the UI tree and triggersuse_build_context_synchronouslybugs afterawaitgaps. SINT binds lifecycle ownership directly to route entries inSintRoot, eliminatingBuildContextplumbing without leaking state.
Solving the 4 Pillars: Development Velocity, Maintenance & Audit Savings #
Building an equivalent 4-pillar feature (Reactive State + Derived Value + Scoped DI + Parameterized Route + i18n + Snackbar):
| Dimension | SINT 2.0 | BLoC Stack (bloc + get_it + go_router + intl) |
Riverpod Stack (riverpod + go_router + intl) |
Provider Stack (provider + go_router + intl) |
Legacy GetX |
|---|---|---|---|---|---|
| Packages to Maintain & Audit | 1 (sint) |
5+ external packages | 4+ packages + build_runner |
4+ external packages | 1 (bloated with HTTP/utils) |
| Files Touched per Feature | 1–2 files | 5–6 files (event, state, bloc, locator, router, .arb) |
4–5 files (provider, .g.dart, router, .arb) |
4 files (notifier, MultiProvider, router, .arb) |
1–2 files |
Codegen (build_runner) |
0 generated files | Optional (freezed/injectable) + ARB |
Required (.g.dart + ARB) |
ARB codegen | 0 generated files |
| Feature Boilerplate (LoC) | ~35 LoC | ~165 LoC (4.7× more code) | ~115 LoC (3.3× more code + .g.dart) |
~105 LoC (3.0× more code) | ~40 LoC (no batch/computed) |
| Code Audit & PR Review Surface | Minimal (~70–80% less code to audit) | High (events, copyWith, manual DI teardown, 5 dep trees) |
Medium–High (generated .g.dart + WidgetRef plumbing) |
Medium (manual notifyListeners + context wiring) |
High (global leaks, string keys) |
| State Granularity (S) | Fine-grained Signals (Obx $O(1)$, batch, computed, untrack) |
Async Stream + immutable copyWith |
Provider graph (ConsumerWidget) |
Coarse object (ChangeNotifier) |
Unbatched .obs (stale branch leaks) |
| DI ↔ Router Lifecycle (I ↔ N) | Native ($O(M)$ auto-dispose on route pop) | Manual BlocProvider / GetIt scopes |
Coupled to widget unmount (autoDispose) |
Coupled to BuildContext subtree |
$O(N \times M)$ scan / string-key collisions |
| Route Matching (N) | Multi-Level Prefix Trie ($O(\text{depth})$) | External (go_router) |
External (go_router) |
External (go_router) |
Linear / 1st-segment regex scan |
| Flutter 3.47+ Standalone UI | Native (SintApp) |
Manual host setup | Manual host setup | Manual host setup | Unsupported (#3469) |
Engineering & Audit Time Impact: Consolidating
S · I · N · Tinto a single deterministic contract reduces per-feature code volume by 70%–78%, eliminatesbuild_runnerwait times, and cuts PR review & security audit time by ~3×–4×—auditors verify 1 cohesive ~35 LoC file with automatic route-bound teardown (onClose) and 1 dependency tree, instead of tracing state mutations, manual disposal, and version compatibility across 5–6 files and 5 third-party packages.
Verified 4-Pillar Benchmarks (four_pillars_benchmark_test.dart) #
How is
Sint.batchfaster than both unbatchedRxandChangeNotifier/BLoC?
- Inside SINT (
0.23 µsbatched vs0.37 µsunbatched — 1.6× faster): Mutating 4 fields (items,price,tax,discount) withoutSint.batchimmediately recomputes derived state (total) and invokes downstreamObxlisteners 4 separate times. InsideSint.batch, each mutation sets a zero-allocation boolean flag (_queuedInBatch = true, ~1ns) and defers evaluation until the block exits—recomputingtotal1 single time and notifyingObx1 single time (75% less work).- Against
ChangeNotifier(0.90 µs) &BLoC(1.02 µs) — 4.0× to 4.5× faster: On a 20-widget screen where only 1 widget readstotal, coarse model/stream patterns notify all 20 widgets on every mutation ($4 \times 20 = \mathbf{80\text{ widget callbacks}}$). SINT's fine-grained per-signalObxgraph notifies the 19 unrelated widgets 0 times and the 1 target widget 1 time ($\mathbf{1\text{ callback vs }80}$).
| Workload | SINT 2.0 Median | Baseline / Alternative Median | Result |
|---|---|---|---|
| Pillar S — 20-Widget Screen, 4-Field Transaction + Derived Total | 0.23 µs/op (Sint.batch + Computed) |
0.37 µs/op (Unbatched Rx)0.90 µs/op (ChangeNotifier)1.02 µs/op (Immutable State Copy) |
1.6× faster than unbatched Rx4.0× – 4.5× faster than ChangeNotifier / BLoC |
Pillar N — 1,000 Shared-Prefix Routes (/api/item999/:id) |
2.56 µs/op (Multi-Level Trie) |
250.48 µs/op (1st-segment / linear regex scan) |
97.8× faster ($O(\text{depth})$ constant scaling) |
Pillar I — Hot Typed/Tagged Dependency Lookup (Sint.find<T>) |
0.021 µs/op (Reified Type registry) |
— | ~47M lookups/sec (Web/Wasm minification-safe) |
Full S·I·N·T Cycle (Route Match + Sint.find + batch/computed + .trParams) |
3.57 µs/op |
— | ~280,000 complete 4-pillar cycles/sec |
Migrating from GetX #
- Replace
get:withsint: ^2.0.0inpubspec.yaml. - Replace
import 'package:get/get.dart';withimport 'package:sint/sint.dart';. - Zero-friction compatibility in
2.x: ExistingGet.,GetxController,GetMaterialApp,GetPage,GetBuilder, andGetRouterOutletcalls continue to compile with@Deprecatednotices so you can migrate toSint*symbols incrementally before3.0.0.
Documentation & Resources #
- Pillar Guides: State · Injection · Navigation · Translation
- Standalone Material / Cupertino Migration: MIGRATION_DESIGN_SYSTEMS.md
- Benchmarks & Methodology: test/benchmarks/README.md · performance/README.md
- Release History & Roadmap: CHANGELOG.md · ROADMAP.md
License #
Released under the MIT License. Part of the Open Neom ecosystem.