flow_vm 1.1.1 copy "flow_vm: ^1.1.1" to clipboard
flow_vm: ^1.1.1 copied to clipboard

State management solution for Flutter applications, providing a streamlined and efficient way to manage ViewModel-based architectures.

flow_vm #

pub.dev license: MIT

flow_vm is a lightweight, fast, and predictable state management library for Flutter based on the ViewModel concept with first-class support for MVVM and MVI (via Intents).

Highlights #

  • MVVM core with a small, focused API
  • Intents for MVI-style state transitions and side effects
  • Widgets for building and listening to data flows
  • Built-in intent transformers (concurrent, sequential, debounced)
  • Observer hooks for analytics/debugging of intents and mutations
  • High performance with minimal rebuilds
  • Type-safe and testable by design

Install #

Add flow_vm to your pubspec.yaml:

dependencies:
  flow_vm: ^1.1.1

Quick Start #

Create a simple ViewModel with a DataFlow and render it with FlowBuilder:

import 'package:flow_vm/flow_vm.dart';
import 'package:flutter/material.dart';

class SimpleCounterVM extends SimpleViewModel {
  late final DataFlow<int> counterFlow = dataFlow(0);

  void onIncrement() => update(counterFlow).change((value) => value + 1);
}

class SimpleCounterScreen extends StatelessWidget {
  const SimpleCounterScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Disposer<SimpleCounterVM>(
      create: (_) => SimpleCounterVM(),
      builder: (context, viewModel) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text('You have pushed the button this many times:'),
                FlowBuilder(
                  flow: viewModel.counterFlow,
                  builder: (context, count) => Text(
                    '$count',
                    style: Theme.of(context).textTheme.headlineMedium,
                  ),
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: viewModel.onIncrement,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        );
      },
    );
  }
}

Intents (MVI) #

Use intent to model user actions and orchestrate state updates and side effects in one place.

class ExtendedCounterVM extends ViewModel {
  late final stateFlow = dataFlow(0);
  late final actionsFlow = actionFlow<String>(); // side effects

  void onIncrement() => intent(
        intentKey: #onIncrement,
        action: (Updater update) {
          final next = stateFlow.value + 1;
          update(stateFlow).set(next);
          update(actionsFlow).set('show success toast');
        },
      );
}

Intent transformers #

Control concurrency and handler behavior for intents. By default, processing is concurrent. You can choose sequential, concurrent, debouncedRestartable, or debouncedSequential.

class SearchVM extends ViewModel {
  final query = dataFlow('');
  final results = dataFlow<List<String>>([]);

  void onQueryChanged(String text) => intent(
        intentKey: #onQueryChanged,
        transformer: Transformers.debouncedRestartable(const Duration(milliseconds: 300)),
        action: (update) async {
          update(query).set(text);
          final items = await fetch(text);
          update(results).set(items);
        },
      );
}

Available transformers: Transformers.concurrent() (default), Transformers.sequential(), Transformers.debouncedRestartable(duration), Transformers.debouncedSequential(duration).

ViewModelObserver #

Observe the lifecycle of intents and flow mutations — useful for logging, analytics, and debugging.

class LoggerObserver implements ViewModelObserver {
  @override
  void onIntentStart(Symbol intentKey) => debugPrint('start: $intentKey');

  @override
  void onIntentExecuted(Symbol intentKey) => debugPrint('done: $intentKey');

  @override
  void onFlowUpdated(Symbol? intentKey, FlowVm flow, Mutation change) {
    debugPrint('update($intentKey): ${change.oldValue} -> ${change.newValue}');
  }

  @override
  void onIntentCanceled(Symbol intentKey) => debugPrint('canceled: $intentKey');
}

final vm = SimpleCounterVM()..addObserver(LoggerObserver());

Widgets #

  • FlowBuilder<T>: Rebuilds UI when DataFlow<T> emits new values.
  • FlowListener<T>: Listens to actions/one-off events without rebuilding UI.
  • Disposer<VM>: Creates and disposes a ViewModel for a subtree.

Why flow_vm? #

  • Clear separation of state and side effects
  • No boilerplate code generators
  • Simple migration path from classic MVVM to MVI
  • Works across all Flutter platforms

Example App #

Explore the examples under example/ showcasing simple and extended patterns with Bloc and Riverpod comparisons.

Testing #

The repository includes unit and widget tests for ViewModel, observers, listeners, and concurrency. Run with flutter test.

Roadmap #

  • More recipes and docs
  • DevTools integration examples
  • Additional intent transformers and utilities

License #

MIT License — see LICENSE.

1
likes
150
points
414
downloads

Publisher

unverified uploader

Weekly Downloads

State management solution for Flutter applications, providing a streamlined and efficient way to manage ViewModel-based architectures.

Repository (GitHub)
View/report issues

Topics

#mvvm #mvi #state-management #clean-architecture

Documentation

API reference

License

MIT (license)

Dependencies

flutter, stream_transform

More

Packages that depend on flow_vm