String.fromEnvironment
(--dart-define), which is fixed at build time. DebugEnv adds a runtime
override layer, persisted in SharedPreferences, so a tester can re-point the
app at a different servers, change the deployment mode or
debug level, and flip feature flags without rebuilding.
How it works
Initialize early (debug only)
In your debug-only setup, load persisted overrides before anything reads
configuration:
await DebugEnv().initialize() (optionally pass your
existing SharedPreferences), then install the hook with
debugLaunchOverride = DebugEnv().overrideOf.Register the arguments
DebugEnv().registerAll([...]) tells the Environment tool which arguments
exist and how to edit them.Read through the hook
Replace
String.fromEnvironment('x') reads with
debugLaunchOverride?.call('x') ?? const String.fromEnvironment('x').Reading values
DebugEnv reads are synchronous (usable inside constructors) once
initialize() has completed, and are convenient inside debug-only code:
CARP example: switching the CAWS server
Read the host through the hook in yourCarpBackend, and expose a
reconfigure() that re-points every CAWS service:
onApply: () => bloc.backend.reconfigure().
EnvEntry reference
Each registered argument is described by an EnvEntry. The type decides which
editor the tool renders.
The
--dart-define name and storage / lookup key (e.g. deployment-mode).Label shown in the app page.
text, enumeration, toggle or integer.Allowed values when
type is enumeration (rendered as a dropdown).The compile-time default, typically
String.fromEnvironment(...). Shown when
no override is set and used by Revert to default.Optional heading (e.g.
Server, Logging) for visual grouping.Optional explanatory text shown under the editor.
Editor types
Managing overrides programmatically
Overrides are stored in
SharedPreferences under the carp_debug_env. prefix.
The Shared Preferences tool hides these keys so they are only managed from
the Environment tool (editing them there would not update the in-memory state).