Skip to main content

an_state 1.3.1 copy "an_state: ^1.3.1" to clipboard
an_state: ^1.3.1 copied to clipboard

A reactive state management library for Flutter, providing seamless integration between ViewModels, Widgets, and reactive observables.

an_state #

an_state is a powerful, lightweight reactive state management library for Flutter. It seamlessly integrates the high-performance reactive engine of an_reactive_state, the robust lifecycle management of an_viewmodel, and the elegant state persistence of remember.

Important

an_state strongly depends on anlifecycle. All core features, including rememberState, rememberMutableState, and context.viewModels(), require a valid Lifecycle context provided within the widget tree.


🚀 Key Features #

  • 🎯 Transparent Reactivity: Based on an_reactive_state, UI updates automatically when state changes. No notifyListeners() or setState() required.
  • 🧬 Lifecycle-Aware: States are bound to the lifecycle of ViewModels or Widgets, ensuring zero memory leaks through automatic resource cleanup.
  • 🏗️ Structured State: Provides RState for mutable values and ComputedState for derived data with automatic dependency tracking.
  • 🔄 Compose-like DX: Use rememberMutableState to persist reactive state across widget rebuilds, offering a developer experience similar to Jetpack Compose.
  • 🛠️ Bridge Utilities: Easily convert legacy ValueNotifier or ChangeNotifier into modern reactive sources.

📦 Getting Started #

Installation #

Add the dependency to your pubspec.yaml:

dependencies:
  an_state: ^1.3.1

Mandatory Lifecycle Setup #

Initialize the lifecycle system at the root of your application:

import 'package:anlifecycle/anlifecycle.dart';

void main() {
  runApp(
    LifecycleApp( // 1. Wrap with LifecycleApp
      child: MaterialApp(
        // 2. Add the navigator observer
        navigatorObservers: [LifecycleNavigatorObserver.hookMode()],
        home: const HomePage(),
      ),
    ),
  );
}

📖 Usage Guide #

1. Local Widget State #

For UI-only state (like a toggle or a counter), use remember extensions to avoid boilerplate StatefulWidgets.

@override
Widget build(BuildContext context) {
  // Persists across rebuilds, disposed when the widget is removed from the tree
  // Requires Lifecycle context
  final isExpanded = context.rememberMutableState(false.asStateOf);

  return Column(
    children: [
      Text("Details are ${isExpanded.value ? 'Visible' : 'Hidden'}"),
      ElevatedButton(
        onPressed: () => isExpanded.value = !isExpanded.value,
        child: const Text("Toggle"),
      ),
    ],
  );
}

2. In ViewModels (Business Logic) #

Define your states using stateMutableOf and stateOf. These states will be automatically disposed of when the ViewModel is cleared.

class UserViewModel extends ViewModel {
  // Use .asStateOf extension to initialize mutable state
  late final username = stateMutableOf("Guest".asStateOf);

  // Computed state depends on username
  late final greeting = stateOf(() => "Hello, ${username.value}!");

  void updateName(String newName) {
    username.value = newName; // UI updates automatically
  }
}

3. In Widgets (UI Layer) #

Access ViewModels and observe states with minimal boilerplate.

@override
Widget build(BuildContext context) {
  // Fetch ViewModel via extension (requires Lifecycle context)
  final vm = context.viewModels<UserViewModel>(factory: UserViewModel.new);

  // Use listenReactiveState to subscribe to a single state and get its value
  final name = context.listenReactiveState(vm.username);
  final message = context.listenReactiveState(vm.greeting);

  // Or use listenReactiveStates to observe multiple reactive states at once.
  // Executes in a reactive scope (`effect`), automatically tracking accessed state dependencies.
  context.listenReactiveStates(() {
    print("Active User: ${vm.username.value}");
  });

  // Consuming AsyncData states with AsyncDataStateExt
  final userState = vm.userState; // RState<AsyncData<User>>
  context.listenReactiveState(userState);

  if (userState.isLoading) {
    return const CircularProgressIndicator();
  } else if (userState.isError) {
    return Text("Error: ${userState.error}");
  }

  return Column(
    children: [
      Text("User: ${userState.data.name}, Message: $message"),
      TextField(onChanged: vm.updateName),
    ],
  );
}

🛠️ Advanced Tools #

Initializers & Extension Getters #

  • .asStateOf: Extension getter on Object, List, Set, Map, and ValueNotifier to convert values directly into RStateComputer (e.g. "Guest".asStateOf, [1, 2].asStateOf, notifier.asStateOf). Preferred over functional initializers.
  • .asNullableStateOf: Extension getter on Object, List, Set, Map, and ValueNotifier for nullable value initializers (e.g. "Guest".asNullableStateOf, map.asNullableStateOf, notifier.asNullableStateOf).
  • nullAsStateOf<T>(): Helper initializer for creating a null value RStateComputer<T?> (e.g. nullAsStateOf<User>()).
  • stateValueOf(T value): Functional initializer for a simple value.
  • stateListOf(List<T> list): Functional initializer for a reactive list.
  • stateMapOf(Map<K, V> map): Functional initializer for a reactive map.
  • stateSetOf(Set<E> set): Functional initializer for a reactive set.

Bridge Tools #

  • stateOfValueNotifier(notifier) (or notifier.asStateOf): Converts a ValueNotifier into a reactive computer.
  • stateOfChangeNotifier(changeNotifier: notifier, computer: (cn) => cn.value): Converts any ChangeNotifier into a reactive computer.
  • stateOfAsync({required T initialValue, Future<T>? future, Stream<T>? stream, ...}): Converts a Future or Stream into a reactive computer. Returns initialValue until an async value is received. Supports lazy factories fFactory/fFactory2(cancellable) and sFactory/ sFactory2(cancellable).
  • stateOfAsyncData<T>({T? initialValue, Future<T>? future, Stream<T>? stream, ...}): Converts a Future or Stream into a reactive AsyncData<T> computer (starts as AsyncData.loading() or AsyncData.value(initialValue)). Supports lazy factories fFactory/fFactory2(cancellable) and sFactory/sFactory2(cancellable).

AsyncDataStateExt Extensions #

Convenient extensions on RState<AsyncData<T>>:

  • State Checkers: isLoading, isError, isData, hasData, data, dataOrNull, error, stackTrace.
  • State Mutators:
    • toLoading(): Sets state to AsyncData.loading().
    • toData(T data): Sets state to AsyncData.data(data).
    • toError(Object error, [StackTrace? st]): Sets state to AsyncData.error(error, st).
    • toDataLoading(): Keeps existing data if hasData is true and sets AsyncData.dataLoading(data), otherwise sets AsyncData.loading().
    • toDataLoadingRaw(T data): Sets state to AsyncData.dataLoading(data).
    • toDataError(Object error, [StackTrace? st]): Keeps existing data if hasData is true and sets AsyncData.dataError(data, error, st), otherwise sets AsyncData.error(error, st).
    • toDataErrorRaw(T data, Object error, [StackTrace? st]): Sets state to AsyncData.dataError(data, error, st).

Optimization #

  • expensiveComputation(Computer<T> computer): Ensures a heavy calculation or registration logic runs only once during the state's lifecycle.

📚 Ecosystem & Underlying Packages #

an_state combines the strengths of several core libraries. For deeper learning on specific features, advanced APIs, or lifecycle details, please refer to their official documentations directly:

  • anlifecycle: Complete lifecycle management system for Flutter applications, routes, and widgets.
  • an_viewmodel: ViewModel architecture component for business logic and lifecycle-aware state scoping.
  • remember: Jetpack Compose-like state persistence and widget memory management.
  • an_reactive_state: Transparent, high-performance reactive state engine with automatic dependency tracking.

📋 Core API Reference #

Method Source Description
asStateOf / asNullableStateOf Extension Extension getters on values ("Guest".asStateOf, list.asStateOf, notifier.asStateOf) to create RStateComputer. Preferred.
stateMutableOf(computer) ViewModel Creates a mutable RState bound to ViewModel.
stateOf(computer) ViewModel Creates a read-only ComputedState.
rememberMutableState(computer) BuildContext Remembers a mutable state in the widget tree.
rememberState(computer) BuildContext Remembers a computed state in the widget tree.
listenReactiveState(state) BuildContext Watches a single state and returns its value (triggers rebuild). Alias: listenRawState.
listenReactiveStates(computer) BuildContext Watches multiple states accessed inside the callback (triggers rebuild).
stateOfAsync(...) Utility Converts a Future or Stream into a reactive computer.
stateOfAsyncData(...) Utility Converts a Future or Stream into a reactive AsyncData<T> computer.
AsyncDataStateExt Extension Convenience methods on RState<AsyncData<T>> for checking and mutating async states (toData, toDataLoading, toDataError, etc.).

📄 License #

This project is licensed under the Apache 2.0 License - see the LICENSE file for details.

1
likes
0
points
401
downloads

Publisher

verified publisheraymtools.com

Weekly Downloads

A reactive state management library for Flutter, providing seamless integration between ViewModels, Widgets, and reactive observables.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

an_async_data, an_lifecycle_cancellable, an_reactive_state, an_viewmodel, anlifecycle, cancellable, flutter, remember

More

Packages that depend on an_state