Skip to content
Back to archipelago.banuacoder.com

Core Scaffolding

How to add an app initializer to a Flutter app ​

Free Reference for initializer_skeleton: every variable, option and package it generates. Command: archipelago generate initializer_skeleton

Generate a pre-launch or post-launch initializer, learn the two-phase startup pattern, and wire your own SDK into the bootstrap sequence.

What you'll learn ​

  • Generating pre-launch and post-launch initializers
  • Understanding the two-phase initialization pattern
  • Wiring initializers into your app's bootstrap sequence
  • Creating custom initializers for your own SDKs

Prerequisites ​

Step 1: Generate an Initializer ​

bash
archipelago generate initializer_skeleton

You will be prompted for:

  • appName: your app name, for example MyApp
  • initializerType: pre_launch or post_launch
  • initializerName: for example Analytics, Payment or FeatureFlags

Or use a config file:

json
{
  "appName": "MyApp",
  "initializerType": "pre_launch",
  "initializerName": "Analytics"
}
bash
archipelago generate initializer_skeleton --config init_config.json

Step 2: Understand the Generated Structure ​

The brick generates one file in the host app. It does not create the app. Run it in an app made by app_scaffold or flutter_modular_monorepo.

text
apps/my_app/lib/host/initializers/
└── analytics_app_initializer.dart

The class extends the Initializer base class and returns an InitializerResult:

dart
class AnalyticsAppInitializer extends Initializer {
  const AnalyticsAppInitializer();

  // Pre-launch only
  @override
  bool get canRunInParallel => false;

  @override
  Future<InitializerResult> initialize() async {
    try {
      // TODO: Add analytics initialization logic
      return const InitializerResult.success();
    } catch (e) {
      return InitializerResult.failure(e);
    }
  }

  @override
  Future<bool> dispose() async => true;
}

Pre-launch initializers run one after another. Post-launch initializers keep the default canRunInParallel of true.

Step 3: Pre-Launch vs Post-Launch ​

The initializerType determines when the initializer runs:

TypeWhen it RunsUse For
pre_launchBefore the first frame renders (blocking)DI setup, route registration, critical SDKs
post_launchAfter the first frame renders (non-blocking)Analytics, feature flags, remote config

Pre-launch initializers block the splash screen. Keep them fast. Post-launch initializers run after your app is visible. The runner applies per-initializer timeouts and reports failures to monitoring.

Step 4: Check the Registration ​

The brick registers the initializer for you. Open pre_launch_initializer.dart or post_launch_initializer.dart and look between the markers:

dart
// archipelago:post_launch_initializers:start
AnalyticsAppInitializer(),
// archipelago:post_launch_initializers:end

Running the brick again does not add a second entry. To remove an initializer, delete its file, its import and its list line. If your app has no markers, post_gen prints a warning and you add the import and entry by hand.

Step 5: Add Your Logic ​

Fill in initialize(). Take what you need as constructor parameters and pass them from the list. Resolve registered types in the host list, not inside the class:

dart
class AnalyticsAppInitializer extends Initializer {
  const AnalyticsAppInitializer(this._tracker);

  final AnalyticTracker _tracker;

  @override
  Future<InitializerResult> initialize() async {
    try {
      await _tracker.setUserProperty('plan', 'free');
      return const InitializerResult.success();
    } catch (e) {
      return InitializerResult.failure(e);
    }
  }

  @override
  Future<bool> dispose() async => true;
}

Then change the generated list entry to AnalyticsAppInitializer(getIt<AnalyticTracker>()). A pre-launch failure stops the app and shows the error screen. A post-launch failure is reported and the app keeps running.

Common Customizations ​

CustomizationHow
Add dependenciesConstructor parameters, filled in the host list
Add error handlingReturn InitializerResult.failure(e) from the catch block
Add timeoutFuture.timeout() inside initialize()
Order initializersReorder the lines between the markers. Entries append in generation order

Next Steps ​