Keyboard Shortcuts

j / kScroll down / up
ggScroll to top
GScroll to bottom
/Open search
?Show this help
EscClose search / help
n / NNext / previous section
hGo to landing
dGo to docs
:Command mode — type section name

Press ? or Esc to close

Deep Dives

State Management

All cubits extend Cubit<State>. State is immutable with copyWith(). Global cubits are singletons; feature cubits are factories. PaginatedCubit is the abstract base for all list screens.

Cubit pattern — the default

// State
class ProfileState {
  final SimpleApiResponse response;

  const ProfileState({required this.response});

  ProfileState initial() => ProfileState(
    response: ApiResponse.initial(data: ProfileModel.empty()),
  );

  ProfileState copyWith({SimpleApiResponse? response}) =>
    ProfileState(response: response ?? this.response);
}

// Cubit
class ProfileCubit extends Cubit {
  final ProfileStore _store;

  ProfileCubit(this._store) : super(ProfileState().initial());

  Future load() async {
    emit(state.copyWith(response: state.response.loading));
    final result = await _store.getProfile();
    emit(state.copyWith(response: result));
  }
}

Bloc — when event traceability is needed

class SearchBloc extends Bloc {
  SearchBloc(this._store) : super(SearchState.initial()) {
    on(_onQueryChanged,
        transformer: debounce(const Duration(milliseconds: 300)));
    on(_onCleared);
  }
}
Use CubitUse Bloc
Simple load / refresh / submitDebounced search, throttled input
Most features — default choiceComplex event → state chains
Low boilerplate neededEvent history / replay needed

Registration rules

TypeRegistrationScope
Feature cubitsregisterFactoryNew instance per screen
Global cubitsregisterLazySingletonShared across entire app

Global cubits: GlobalErrorCubit · ThemeCubit · LocalizationCubit · ConnectivityCubit · LoadingCubit · ToastCubit

PaginatedCubit

Abstract base for all list/paginated screens. Subclass implements only fetchPage(). The rest comes free.

abstract class PaginatedCubit
    extends Cubit>
    with ConnectivityReloadMixin {

  // Subclass implements only this:
  Future, PaginationMeta>> fetchPage(int page, FilterT? filters);

  // Provided out of the box:
  // loadFirst()     — load page 1, replace list
  // loadMore()      — load next page, append
  // refresh()       — pull-to-refresh, reset to page 1
  // applyFilters()  — set filters + reload from page 1
  // clearFilters()  — reset filters + reload
}

ConnectivityReloadMixin auto-registers each PaginatedCubit. On network recovery, onReconnected() is called — paginated screens reload automatically.

UI access pattern

BlocBuilder(
  builder: (context, state) {
    if (state.response.isLoading) return const AppShimmer();
    if (state.response.isFailure) return AppEmptyState.error();
    return ProfileContent(data: state.response.data);
  },
);

@override
void initState() {
  super.initState();
  context.read().load(); // always in initState
}
sam's arch — A Pragmatic Flutter Architecture