GitHub Logo

Osam - it is complex solution for fast and quality mobile developing.

First we will talk about is State aka BaseState<T> object.

The data structure which representing current data in runtime can be called as State.


class AppState extends BaseState<AppState> {
  final counter = Counter();

  List<Object> get props => [counter];

class Counter extends BaseState<Counter> {
  var value = 0;

  StateStream<int> get valueStream => propertyStream((state) => state.value);

  List<Object> get props => [value];

This code means that we have a something like tree of data for our app.

Recommendation: Create a one AppState in main function instead of a lot of states.

The state and it's property are listenable. You can get it by calling 'propertyStream'. It returns StateStream - Bundle with value and it's stream.

Second we talk about is Store.

The purpose of Store is provide 'UseCases'. UseCase could be everything, but I recommend to follow several rules:

  1. UseCase have access to AppState or sub states by passing it in to constructor.
  2. State or states in UseCase must be lib private (underscored "_item = 1").
  3. UseCase should implement interfaces to provide business models or properties of it.
  4. Only UseCase can change States by calling update method.
  5. All repositories you need must be provided via constructor in to UseCase.
  6. UseCase should depends of interfaces not implementations of repositories
abstract class ICounter{
  Future<int> increment(int value);

class CounterUseCase {
  final ICounter _counterRepo;
  final AppState _appState;

  CounterUseCase(this._counterRepo, this._appState);
  Future<void> increment() async {
    final lastValue = _appState.counter.value;
    final newValue = await _counterRepo.increment(lastValue);
    _appState.counter.update((state) => state..value = newValue);

  StateStream<int> get valueStream => _appState.counter.valueStream;

// example