washington 0.0.1-dev.4 icon indicating copy to clipboard operation
washington: ^0.0.1-dev.4 copied to clipboard

A No-Nonsense Global Event Driven State Management package for Flutter.

The No-Nonsense Event Driven State Management solution for Flutter.

WARNING: This package is not ready for production projects.

Feel free to try it prototypes or experiments.

DECLARATION OF INDEPENDENCE

This package was born from a personal desire for a light-weight state
management solution.

Creating my own state managment solution allowed me to adapt to my personal
needs and preferences that I've developed over my years working with Flutter.

When one would try this state management solution, one will find traces of
other well-know solutions that have inspired me.

Washington #

Washington (class) is the capitol of your state management. You will use Washington to dispath events for your application.

Washington is implimented as a singleton allowing you to easily access it from anywhere in your application.

When you want to grab hold of the Washington instance you can use the static instance property.

Washington.instance.dispatch(SomeEvent());

UnitedStates #

You will use UnitedState objects to manage your application's state.

To create these objects, all you have to do is extend the UnitedState class and add handlers for all the events you want your UnitedState to act upon.

Each UnitedState should be responsible for a specific area or feature of your app. For example, you could have a UserState, ProductsState and SettingsState.

class UserState extends UnitedState<User?> {
    UserState() : super(null) {
        addHandler<Login>((event) => ... );
        addHandler<Logout>((event) => ... );
        ...
    }
}

ProTip: To keep the constructor nice and clean it is recommended to create private methods in the class and add them as a handler.

SetState #

To update the state you use the setState function. You can set a new value, and you can also set the isLoading and error properties.

setState(
    User(), // the new value
    isLoading: false,
    error: null,
);

Events #

Events are the things that will trigger change in your application.

An event can be any object you want. You use Washington to dispatch these events. Washington will make sure that the events reach all the UnitedStates so they can react to it.

Because you can dispatch anything as an event, you are able to dispatch events that can be handled by multiple states at the same time allowing you to update different parts of your app with the same event.

You can dispatch a UserLogout event and the UserState can act upon this. But the SettingsState could also use this event to clear all the user's preferences.

class UserLogout {};

class AuthState extends UnitedState<User?> {
    AuthState() : super(null) {
        addHandler<LogoutEvent>(_clearUser);
        ...
    }

    ...
}

class SettingsState extends UnitedState<Settings?> {
    SettingsState() : super(null) {
        addHandler<LogoutEvent>(_clearSettings);
        ...
    }

    ...
}

ProTip: You can also make a UnitedState emit events to create a chain reaction.

This way you could clean up after a user logs out, or navigate to the LoginPage.

Widgets #

When using Washington in your Flutter application you can use a set of convenient widgets that help you build or trigger UI elements based on events and state changes.

StateProvider #

States can be scoped in the widget tree by using StateProviders.

StateProvider<AuthState>(
    create: (context) => AuthState(),
    child: ...
)

When you need to add multiple StateProviders add the same level, consider using a MultiStateProvider. This makes your code more readable.

MultiStateProvider(
    stateProviders: [
        StateProvider<AuthState> (create: (context) => AuthState()),
        StateProvider<SettingsState> (create: (context) => SettingsState()),
    ]
)

StateBuilder #

To build the UI based on the state you can use StateBuilders.

There are two constructors you can use, both with their own use-case.

Default constructor #

When you want to build a widget that has support for different states you might want to use the default constructor. The builder will be called on every state change.

StateBuilder<AuthState,User?>(
    builder: (context, state) => ProfilePage(
        isLoading: state.isLoading,
        user: state.value,
        error: state.error,
    ),
)

StateBuilder.separate #

The separate constructor is ideal for when you want to show totally different widgets based on the state.

It gives you three seperate builder functions for success, loading and error states.

Only the successBuilder is required, the other two are optional. However, when isLoading is set to true or error is not null, and the corresponding builder has not been provided, an assertion error will be thrown.

StateBuilder<AuthState,User?>.separate(
    successBuilder: (context, user) => Profile(user),
    loadingBuilder: (context) => Loading(),
    errorBuilder: (context, error) => Error(error),
)

StateListener #

When you need to trigger one-off actions (like navigating or showing a snackbar) based on state changes, you can use the StateListener.

StateListener differs a little from StateBuilder.

It has a default constructor and three named constructors.

Default constructor #

The default constructor requires a builder function that will be called on every state change. The state that's passed to this builder will contain the value, isLoading and error fields.

StateListener<AuthState,User?>(
    listener: (context, state) => ...,
)

Named constructors #

The named constructors are only called in specific cases.

StateListener<AuthState,User?>.error(
    // Will only be called when the state has an error
    errorListener: (context, state) => ...,
)

StateListener<AuthState,User?>.loading(
    // Will only be called when there is no error,
    // and loading is set to true.
    loadingListener: (context, state) => ...,
)

StateListener<AuthState,User?>.success(
    // Will only be called when there is no error,
    // and loading is set to false.
    successListener: (context, state) => ...,
)

EventListener #

If you want to trigger one-off actions based on the events being dispatched, instead of a state change, you can use the EventListener.

EventListener(
    listener: (context, event) => ...,
)
1
likes
130
pub points
10%
popularity

Publisher

unverified uploader

A No-Nonsense Global Event Driven State Management package for Flutter.

Repository (GitHub)
View/report issues

Documentation

API reference

License

Icon for licenses.MIT (LICENSE)

Dependencies

flutter, provider

More

Packages that depend on washington