✦ Dart & Flutter  ·  v0.34.0

Reactive state,
the way it should feel.

Live Cells brings true reactivity to your Dart & Flutter data layer. Declare cells, compose them, and let your UI respond automatically—no boilerplate, no manual listeners, no dispose().

Get Started View on pub.dev
flutter pub add live_cells

Built for Flutter's
reactive model

Everything you need to write expressive, composable state logic without fighting the framework.

⚡

Automatic propagation

Observers are notified automatically when cell values change. Define a computed cell once and it stays in sync forever.

↔

Two-way data flow

Unique among reactive libraries: data can flow in both directions. Bind a text field to a number cell with a single line.

🗑

No dispose() calls

Cells manage their own lifecycle. No more forgetting to remove listeners or call dispose()—memory cleans itself up.

🧩

Composable expressions

Write a + b and get a cell whose value is always the sum. Functional composition, no listener wiring.

🎛

Widget integration

Drop-in reactive widgets—LiveSwitch, LiveTextField, CellWidget—bind directly to cells with no state management ceremony.

💾

State restoration

Persist and restore app state with minimal boilerplate. Cells that survive process death, with no extra wiring.

Less ceremony,
more clarity

See the difference when reactive state is a first-class citizen of your data layer.

Without Live Cells ValueNotifier
final a = ValueNotifier<int>(0);
final b = ValueNotifier<int>(1);
late final sum = ValueNotifier<int>(0);
// Wire listeners manually
void _updateSum() {
  sum.value = a.value + b.value;
  print('${a.value} + ${b.value} = ${sum.value}');
}
// Remember to add AND remove
a.addListener(_updateSum);
b.addListener(_updateSum);
...
@override
void dispose() {
  a.removeListener(_updateSum);
  b.removeListener(_updateSum);
  a.dispose();
  b.dispose();
  sum.dispose();
  super.dispose();
}
With Live Cells MutableCell
final a = MutableCell(0);
final b = MutableCell(1);
// Reactive expression — just works
final sum = a + b;
// Observe — no manual wiring
ValueCell.watch(() {
  print('${a()} + ${b()} = ${sum()}');
});
// No dispose() needed.
// Ever.

One abstraction
to learn

The cell is the only primitive. Master it and you have mastered the library.

// Mutable cells

The entry point to reactivity. Set a value; observers fire automatically.

final count = MutableCell(0);
count.value++;   // triggers observers

// Computed cells

Derive state from other cells with plain expressions or ValueCell.computed.

final doubled = count * 2.cell;
// or
final label = ValueCell.computed(
  () => 'Count: ${count()}',
);

// Two-way flow

Bind a numeric cell to a text field. Changes flow both ways automatically.

final n = MutableCell<num>(0);

LiveTextField(
  content: n.mutableString(),
);

// Widget binding

Rebuild only the widgets that need to—no setState, no provider lookup.

final count = MutableCell(0);
final isEnabled = MutableCell(true);

...          

CellWidget.builder(() =>
  Text('${count()}')
);

...

LiveSwitch(value: isEnabled);

// Async cells

Await futures held in cells. Computed cells propagate loading state too.

final isLoading = (c1, c2).isCompleted.not();

final sum = ValueCell.computed(() {
  final (a, b) = (c1, c2).wait();
  return a + b;
});

// Error handling

Exceptions propagate through cell chains. Handle them where it makes sense.

final str = MutableCell('0');

final n = ValueCell.computed(
  () => int.parse(str()),
);

final valid = (n > 0.cell)
  .onError(false.cell);

Beyond ChangeNotifier

Live Cells solves the friction points you've accepted as normal in Flutter state management.

✓

Unopinionated

No forced architecture. Use as much or as little of Live Cells as you need. Integrate incrementally.

✓

Drop-in for ValueListenable

The .listenable property wraps any cell as a ValueListenable—use it wherever Flutter expects one.

✓

Previous value access

Need the last value of a cell? Just use cell.previous—it's a cell too.

✓

Code-gen for your types

live_cell_extension generates property accessors so you can use cell syntax on your own model classes.

Used by developers building with Flutter

Using Live Cells in your app? Open a PR to add it here →

Ready to make your state actually reactive?

Read the docs → GitHub

Up and running
in minutes

Three steps from zero to reactive Flutter app.

Add the dependency

flutter pub add live_cells — or add live_cells: ^0.34.0 to your pubspec.yaml.

Import & define cells

Import package:live_cells/live_cells.dart and declare your state as MutableCell instances at the top of your logic layer.

Bind to widgets

Wrap rebuilding UI in CellWidget.builder, or swap Flutter widgets for their Live* equivalents. Done.