OSAM

GitHub Logo This state management implements best solutions of Redux, Bloc, Provider and SOLID principles.

Glossary

  • Domain layer

Store - is a Singleton that stores your State of application.

State - is a class that contains data like primitives, collections and other states.

Event - is a parent class for ModificationEvent that can contains "bundle" (payload).

ModificationEvent - is Event that implements Reducer to modify State of application.

Reducer - is a method in ModificationEvent that calls method of target State and returns it.

Middleware - is a class that working between sending event and calling it's Reducer and contains Conditin's to add and handle with your business logic.

Notice

  • To catch your custom event in middleware, just create your own Event by extending Event or ModificationEvent.

Example:

  • ModificationEvent
class IncrementEvent extends ModificationEvent<AppState, int> {
  IncrementEvent({int bundle});

  @override
  get reducer => (AppState state, int bundle) => state..increment();
}
  • Event for handle some actions
class SomeSideEffectEvent extends Event<AppState, void>{}
  • Middleware catching event
class MyMiddleware extends Middleware<Store<AppState>> {
  bool isIncrement(Event event) {
    if (event is IncrementEvent) {
      Future.delayed(Duration(seconds: 1), () {
        store.dispatchEvent(event: IncrementEvent());
      });
    }
    return nextEvent(true);
  }

  @override
  List<Condition> get conditions => [isIncrement];
}
  • Presentation layer

StoreProvider - is a wrapper of your entry point widget and Store to provide Store for all of Presenter's using Provider package (https://pub.dev/packages/provider).

Presenter - is a class that have access to Store and being glue based of Stream's to separate domain and presentation layers.

PresenterProvider - is a wrapper of your widget and Presenter to provide Presenter for all of widgets down of widget tree using Provider package.

  • Rules
  1. stateStream and propertyStream emits it's state/property only if last state is not equal to next state/property.

  2. State sends new it's condition to stateStream only by dispatching ModificationEvent to Store

  3. Modify your State's only by dispatching ModificationEvent's.

  4. Don't call StoreProvider and Store in widgets, use Presenter's and PresenterProvider's to handle with Store.

  5. Use Middlewares for all of your business rules.

  6. To throw Event through all of Middleware conditions stack, you must return in all of conditions this call:

nextEvent(true); // or false if you wouldn't
  1. "Recommendation" try to use worker_manager package to save your fps. https://pub.dev/packages/worker_manager
  • Special features
  1. State supports comparison based on comparison of its meaningful props. So you will never get the same as previous state in stateStream. So your UI won’t be called with the same data.

  2. State is the mutable class. Garbage collector won’t work so often. And already created Objects will be reused instead of creating new same ones.

  3. Store tracks app lifecycle and save its State when app goes to background and restore it when app back to foreground using Hive DB (https://pub.dev/packages/hive). So user can continue with the place/screen he stopped.

  4. Presenter supports dispose. So if user goes to another screen all needed clean up and closing subscriptions to State's will be done.

  5. In Presenter's you can listen to not only all new State but also propertyStream for listening only one property (which can be property of State or mapped Object from State). So UI will be rebuilt less time.

Best way I know, to understand how to use it - it's look at examples, enjoy ! =)

Examples

https://github.com/Renesanse/popular_newss

https://github.com/Renesanse/osam/tree/master/examplee

#Author

  • Daniil telegram: @dsrenesanse

Libraries

base_state
comparable_wrapper
event
middleware
osam
parrent_store
persist_repository
presenter
store
store_provider