Learn
Presenter as the adaptation boundary
Convert complete business input into presentation-ready data, public feature actions, and guarded transient effects.
v0.1.0-dev.1Intermediate
Presenter as the adaptation boundary
Presenter stands between Model and View. Its central job is not forwarding state but assigning presentation meaning.
dart
final class CounterPresenter extends Presenter<
CounterModel,
CounterViewState,
CounterEffect,
CounterEnvironment> {
@override
CounterViewState buildViewState(CounterEnvironment environment) {
return CounterViewState(
valueLabel: environment.formatNumber(model.value),
canIncrement: model.value < 100,
);
}
void increment() {
if (model.value >= 100) {
emitEffect(const CounterLimitReached());
return;
}
model.increment();
}
}
What Presenter should do
- combine several business snapshots into one screen state;
- convert domain values into localized or formatted text;
- derive visibility, enabled state, loading, empty, and error variants;
- expose named feature actions to View;
- compare meaningful Model transitions before emitting an effect;
- keep small resettable presentation choices when appropriate.
What Presenter should not do
- own the UseCase, Repository, or application manager behind Model;
- store
BuildContextfor later use; - execute side effects from
buildViewState; - retain business truth that must outlive the View;
- expose Model directly to child widgets.
Presentation-local state
A selected local tab or expanded details panel can live in Presenter when resetting it with the feature is acceptable. After changing such state, call invalidateView(). If resetting would violate product behavior, the value belongs in a longer-lived business boundary and therefore enters Presenter through Model.