EMPIRE
A simple, lightweight state management library for Flutter
Features
A Model-View-ViewModel (MVVM) like approach to state management. Less boiler plate and significantly reduced clutter in your Widget build functions than other state management solutions.
Usage
A simple example using the classic Flutter Counter App.
counter_view_model.dart
class CounterViewModel extends EmpireViewModel {
late final EmpireProperty<int> count;
@override
void initProperties() {
count = createProperty(0);
}
Future<void> incrementCounter() async {
count(count.value + 1);
}
}
counter_page.dart
class CounterPage extends EmpireWidget<CounterViewModel> {
const CounterPage({Key? key, required CounterViewModel viewModel})
: super(key: key, viewModel: viewModel);
@override
EmpireState<EmpireWidget<EmpireViewModel>, CounterViewModel> createEmpire() => _CounterPageState(viewModel);
}
class _CounterPageState extends EmpireState<CounterPage, CounterViewModel> {
_CounterPageState(super.viewModel);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Example')),
body: Center(
child: Text('${viewModel.count}'),
),
floatingActionButton: FloatingActionButton(
onPressed: viewModel.incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
main.dart
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Empire State Example',
home: CounterPage(
viewModel: CounterViewModel(),
),
);
}
}
Our business logic is clearly separated from the UI in a clean and simple way. Even in more complicated situations where, with other state management solutions, it’s common to create separate classes to represent your state, with Empire this is as complicated as it gets while supporting even the most complex scenarios.
By extending EmpireWidget
and EmpireState
and supplying an EmpireViewModel
, your UI will automatically update whenever an EmpireProperty
in your view model changes.
Application Wide State Management
What if you have application wide data that you want all your widgets to have access to at any time. Enter the Empire
widget.
Create a ViewModel for your application:
application_view_model.dart
class ApplicationViewModel extends EmpireViewModel {
late final EmpireProperty<User?> loggedInUser;
@override
void initProperties() {
loggedInUser = createProperty(null);
}
void updateUser(User user) => loggedInUser(user);
}
Make the child of your CupertinoApp
or MaterialApp
an Empire
widget. Supply a function to generate a unique application state id. This tells your app it needs to refresh the widget tree below your your Empire
widget. In this example, we are using the Uuid package to handle creating a unique ID, but we leave it up to you to decide what dependencies you want to include in your application. This function will get called anytime the loggedInUser
property is changed in the ApplicationViewModel
and trigger the UI for your app to update.
main.dart
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Empire(
ApplicationViewModel(),
onAppStateChanged: () => const Uuid().v1(),
child: Builder(
builder: (context) {
final appViewModel = Empire.viewModelOf<ApplicationViewModel>(context);
final loggedInUser = appViewModel.loggedInUser;
return Column(
children: [
Text('User: ${loggedInUser}'),
TextButton(
child: Text('Update User'),
onPressed: () => appViewModel.updateUser(User('foo', 'bar')),
),
],
);
},
),
),
);
}
}
Additional information
This package has ZERO dependencies on any other packages.
You can find the full API documentation here
Developed by:
© 2022 Strive Business Solutions