Skip to content

State Management

Flutter Server Box uses Riverpod with code generation for state management.

Simple state that can be read and written:

@riverpod
class Settings extends _$Settings {
@override
SettingsModel build() {
return SettingsModel.defaults();
}
void update(SettingsModel newSettings) {
state = newSettings;
}
}

State that loads asynchronously with loading/error states:

@riverpod
class ServerStatus extends _$ServerStatus {
@override
Future<StatusModel> build(Server server) async {
return fetchStatus(server);
}
Future<void> refresh() async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() => fetchStatus(server));
}
}

Real-time data from streams:

@riverpod
Stream<CpuUsage> cpuUsage(CpuUsageRef ref, Server server) {
return cpuService.monitor(server);
}
state.when(
data: (data) => DataWidget(data),
loading: () => LoadingWidget(),
error: (error, stack) => ErrorWidget(error),
)

Parameterized providers:

@riverpod
List<Container> containers(ContainersRef ref, Server server) {
return containerService.list(server);
}

Providers that dispose when no longer referenced:

@Riverpod(keepAlive: false)
class TempState extends _$TempState {
// ...
}
  1. Use code generation: Always use @riverpod annotation
  2. Co-locate providers: Place near consuming widgets
  3. Avoid singletons: Use providers instead
  4. Layer correctly: Keep UI logic separate from business logic
class ServerWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final status = ref.watch(serverStatusProvider(server));
return status.when(...);
}
}
ref.read(settingsProvider.notifier).update(newSettings);