| j / k | Scroll down / up |
| gg | Scroll to top |
| G | Scroll to bottom |
| ⌘K / / | Open search |
| ? | Show this help |
| Esc | Close search / help |
| n / N | Next / previous section |
| h | Go to landing |
| d | Go to docs |
| : | Command mode — type section name |
Press ? or Esc to close
All cubits extend Cubit<State>. State is immutable with copyWith(). Global cubits are lazy singletons; feature cubits are factories.
// State
class ProfileState {
final SimpleApiResponse<ProfileModel> userProfileResponse;
final SimpleApiResponse<bool> certificateMutationStatus;
const ProfileState({
required this.userProfileResponse,
required this.certificateMutationStatus,
});
factory ProfileState.initial() => ProfileState(
userProfileResponse: ApiResponse.initial(data: ProfileModel.empty()),
certificateMutationStatus: ApiResponse.initial(data: false),
);
ProfileState copyWith({
SimpleApiResponse<ProfileModel>? userProfileResponse,
SimpleApiResponse<bool>? certificateMutationStatus,
}) => ProfileState(
userProfileResponse: userProfileResponse ?? this.userProfileResponse,
certificateMutationStatus: certificateMutationStatus ?? this.certificateMutationStatus,
);
}
// Cubit
class ProfileCubit extends Cubit<ProfileState> {
final ProfileStore _store;
ProfileCubit(this._store) : super(ProfileState.initial());
Future<void> fetchMyProfile() async {
emit(state.copyWith(userProfileResponse: state.userProfileResponse.loading));
final result = await _store.getMyProfile();
emit(state.copyWith(userProfileResponse: result));
}
Future<void> createCertificate(CertificateBody body) async {
emit(state.copyWith(certificateMutationStatus: ApiResponse(status: ActionStatus.loading, data: false)));
final result = await _store.createCertificate(body);
emit(state.copyWith(
certificateMutationStatus: result.isSuccess
? ApiResponse(status: ActionStatus.success, data: true)
: ApiResponse(status: ActionStatus.failure, message: result.message, data: false),
));
if (result.isSuccess) await fetchMyProfile();
}
} abstract class PaginatedCubit<ItemT, FilterT, ExtraT>
extends Cubit<OffsetPaginatedState<ItemT, FilterT, ExtraT>>
with ConnectivityReloadMixin {
// Subclass implements only this:
Future<ApiResponse<List<ItemT>, OffsetPaginationMeta>> fetchPage(int page, FilterT? filters);
// Provided out of the box:
Future<void> loadFirst() async { ... } // load page 1, replace list
Future<void> loadMore() async { ... } // load next page, append
Future<void> refresh() async { ... } // pull-to-refresh, reset to page 1
Future<void> applyFilters(FilterT f) async { ... } // set filters + reload
Future<void> clearFilters() async { ... } // reset filters + reload
} BlocBuilder<ProfileCubit, ProfileState>(
builder: (context, state) {
if (state.userProfileResponse.isLoading) return const AppShimmer();
if (state.userProfileResponse.isFailure) return AppEmptyState.error();
return ProfileContent(data: state.userProfileResponse.data);
},
);
@override
void initState() {
super.initState();
context.read<ProfileCubit>().fetchMyProfile(); // always in initState
} | Type | Registration | Scope |
|---|---|---|
| Feature cubits | registerFactory | New instance per BlocProvider |
| Global cubits | registerLazySingleton | Shared across entire app |
Global cubits: GlobalErrorCubit · ThemeCubit · LocalizationCubit · ConnectivityCubit · LoadingCubit · ToastCubit