Skip to content
Efra Espada edited this page Jul 2, 2024 · 1 revision

A state is the element that will give form to a screen.

Not to be confused with the widget state, this state belongs to the domain layer, which holds all the information used on the screen.

This state is formed from the object library which manages all the serialization and deserialization of our state.

If you already use object in your project for your data models this will be familiar to you, otherwise you should keep these points in mind:

  • This state is defined in the ViewModel and can be accessed from the Presenter and the View (Widget).

  • Each time you update the variables contained in your state, you must have object regenerate the model internally.

dart run object:build
  • The primitive variables must be initialized, null elements must not be defined. Only complex classes are null.
class MainState extends MainStateGen {
  @override
  @Field(name: 'counter')
  int counter = 0;

  @override
  @Field(name: 'information')
  Information? information;

  MainState();
}

Usage

From the ViewModel

After creating your new screen, define a method to modify the state at the base of the ViewModel.

abstract class BaseMainViewModel extends ViewModel<MainState> {
  @override
  MainState state = MainState();
  
  /// Simulates a counter increment in the example.
  Future<void> remoteIncrementCounter();
}

From the ViewModel, edit or manage the state variables. When you have made all the necessary modifications, invoke the callback() method.

class MainViewModel extends BaseMainViewModel {
  @override
  Future<void> remoteIncrementCounter() async {
    await Future.delayed(const Duration(seconds: 5));
    state.counter++;
    callback();
  }
}

From the Presenter

abstract class BaseMainPresenter extends MainPresenterDefinition {
  @override
  MainViewModel model = MainViewModel();

  void incrementCounter();
}
class MainPresenter extends BaseMainPresenter {
  @override
  void incrementCounter() async {
    showTextSnack("Incrementing counter. It was ${state.counter}");
    await model.remoteIncrementCounter();
    showTextSnack("Incremented counter");
  }
}

From the View

class MainPageState extends MainLifecycle {
  @override
  Widget onBuild(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text("Main Screen"),
      ),
      body: ListView(
        physics: const BouncingScrollPhysics(),
        children: [
          const Padding(padding: EdgeInsets.all(7.5)),
          const Center(
            child: Text(
              'You have pushed the button this many times:',
            ),
          ),
          const Padding(padding: EdgeInsets.all(7.5)),
          Center(
            child: Text(
              '${state.counter}',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: presenter.incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}