flutter_dva 1.0.1 copy "flutter_dva: ^1.0.1" to clipboard
flutter_dva: ^1.0.1 copied to clipboard

flutter dva framework

flutter_dva #

pub package

A Flutter state management library inspired by dva, built on top of Redux architecture. It provides a structured and scalable way to manage application state with models, reducers, and effects.

pub.dev

Features #

  • Model-based state management — Encapsulate state, reducers, and effects into one unit
  • Async effects — Handle side effects like API calls with ease
  • Plugin system — Extend functionality with hooks (onError, onAction, onStateChange, etc.)
  • Built-in loading plugin — Automatically track loading states of async effects
  • State persistence — Built-in Redux persist support using SharedPreferences
  • Single store — Global singleton store with namespace-partitioned state
  • Type-safe — Full Dart type support for state and actions

Installation #

Add this to your pubspec.yaml:

dependencies:
  flutter_dva: ^1.0.1

Or use the latest version directly from the repository:

dependencies:
  flutter_dva:
    git:
      url: https://gitee.com/liuhong1happy/flutter_dva

Quick Start #

1. Define a Model #

A model encapsulates state, reducers (synchronous state updates), and effects (asynchronous operations).

import 'package:flutter_dva/flutter_dva.dart';

class CountState extends DvaState {
  CountState({this.count = 0});
  num? count;

  @override
  void fromJson(Map<String, dynamic> json) {
    count = json['count'];
  }

  @override
  Map<String, dynamic> toJson() => <String, dynamic>{
    'count': count,
  };
}

class CounterModel implements Model<CountState> {
  @override
  String namespace = 'counter';

  @override
  StoreOfState<CountState> state = StoreOfState<CountState>(state: CountState());

  @override
  Map<String, ReducerFuction> reducers = {
    'add': (StoreOfState<dynamic> lastState, DvaAction action) {
      CountState s = lastState.getState() as CountState;
      s.count = (s.count ?? 0) + 1;
      lastState.setState(s);
      return lastState;
    },
  };

  @override
  Map<String, EffectFunction> effects = {
    'asyncAdd': (DvaAction action, ModelEffects effects) async {
      await Future.delayed(const Duration(seconds: 1));
      effects.dispatch(DvaAction('add', null));
    },
  };
}

2. Create the Dva Instance #

import 'package:flutter_dva/flutter_dva.dart';

Dva dva = Dva(DvaOpts(
  models: <Model<dynamic>>[
    CounterModel(),
  ],
));

3. Boot the App #

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  WidgetCreatorFunction app = await dva.start(() => MyApp(), () async {
    // Optional initialization (e.g., state persistence)
  });
  return runApp(app());
}

4. Connect Widget to State #

Use Connect (an abstract State) to subscribe to state changes:

import 'package:flutter_dva/flutter_dva.dart';

class MyHomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyHomePageState();
}

class MyHomePageState extends Connect<MyHomePage> {
  void increment() {
    props?.dispatch('counter/add');
  }

  @override
  Widget build(BuildContext context) {
    // Access state from the global store
    num? count = state?.getState('counter')?.count;
    return Scaffold(
      body: Center(child: Text('$count')),
      floatingActionButton: FloatingActionButton(
        onPressed: increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

Core Concepts #

Model #

Each model has:

  • namespace — Unique key to identify the model's state slice
  • state — Initial state (StoreOfState<T>)
  • reducers — Synchronous functions that update state
  • effects — Async functions for side effects, dispatch actions to reducers

Reducer #

Reducers are pure functions that take the current state and an action, and return a new state:

(StoreOfState<dynamic> lastState, DvaAction action) {
  lastState.setState(newValue);
  return lastState;
}

Effect #

Effects handle asynchronous operations like HTTP requests. They can dispatch actions to reducers:

(DvaAction action, ModelEffects effects) async {
  final data = await fetchData();
  effects.dispatch(DvaAction('save', data));
}

Connect #

Connect<T extends StatefulWidget> is a base class that automatically subscribes to the Redux store. State changes trigger setState().

Provider #

A singleton that provides access to the Store instance from anywhere in the app:

Store store = Provider().store!;
await store.dispatch(DvaAction('counter/add', null));

Plugins #

dva-loading #

Automatically tracks loading states for async effects:

Dva dva = Dva(DvaOpts(
  models: [...],
));

dva.use(createLoading());

You can then access loading states from the loading namespace:

// Access in your code
bool isGlobalLoading = Provider().store!.getStateByKey<bool>('loading')?.global;

redux-persist #

Persist state using SharedPreferences:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  WidgetCreatorFunction app = await dva.start(() => MyApp(), () async {
    final ReduxPersistor persistor = ReduxPersistor(
      store: dva.store!,
      heartBeat: 1500,
    );
    await persistor.persist(); // Restore persisted state
  }, waitCallabck: true);
  return runApp(app());
}

Note: Your state classes should implement fromJson() and toJson() for persistence to work.

Hooks #

Customize behavior with lifecycle hooks:

DvaOpts(
  models: [...],
  onError: (dynamic error, Map<String, dynamic> context) {
    print('Error: $error');
  },
  onAction: (DvaAction action) {
    print('Action: ${action.type}');
  },
  onStateChange: (StoreOfState state, DvaAction action) {
    print('State changed: ${state.namespace}');
  },
)

API Reference #

API Description
Dva Main class, initializes models and creates the Redux store
DvaOpts Configuration options for Dva (models, hooks, initialState)
Model<T> Interface for defining a state model
Connect<T> Base State class that subscribes to store changes
Provider Singleton providing access to the Store
StoreOfState<T> Wrapper around state with update timestamp
DvaAction Action object with type and payload
DvaReducer<T> Reducer implementation specific to a model
DvaLoadingState State class for the loading plugin
ReduxPersistor State persistence manager using SharedPreferences
createLoading() Creates a loading plugin hook
dvaDispatch(type, payload) Global dispatch helper function
dvaGetStateByKey<T>(key) Global state access helper function

Examples #

Check out the example project for a complete Flutter counter application that demonstrates:

  • Model definition with reducers and effects
  • State persistence with SharedPreferences
  • Widget-to-store connection using Connect

License #

MIT

0
likes
0
points
344
downloads

Publisher

verified publisher17ued.top

Weekly Downloads

flutter dva framework

Homepage

License

unknown (license)

Dependencies

flutter, shared_preferences

More

Packages that depend on flutter_dva