clean_init

A Flutter package that provides a simple and flexible initialization framework for your applications.

Features

  • Bootstrap initialization with state management
  • Built-in provider - no need to add it to your provider list
  • Customizable initialization states (loading, error, initialized)
  • Loading progress tracking with optional progress and stage data
  • Flexible UI customization with both widget and builder options
  • Clean separation of concerns

Usage

Basic Example

import 'package:clean_init/clean_init.dart';

CleanInitContainer(
  init: (setInitState) async {
    try {
      // Your initialization logic
      await loadConfig();
      await initializeServices();

      setInitState(CleanInitState.initialized);
    } catch (e) {
      setInitState(CleanInitState.error(ErrorData(message: e.toString())));
    }
  },
  initializedWidget: YourMainApp(),
)

With Custom Loading and Error UI

CleanInitContainer(
  init: (setInitState) async {
    try {
      setInitState(CleanInitState.loading);

      // Track progress
      setInitState(CleanInitState.loadingWithData(
        LoadingData(progress: 0.5, stage: 1),
      ));

      await Future.delayed(Duration(seconds: 2));
      setInitState(CleanInitState.initialized);
    } catch (e) {
      setInitState(CleanInitState.error(ErrorData(message: e.toString())));
    }
  },
  loadingWidget: Center(child: CircularProgressIndicator()),
  errorWidget: Center(child: Text('Something went wrong!')),
  initializedWidget: YourMainApp(),
)

Using Builders for Advanced Customization

CleanInitContainer(
  init: (setInitState) async {
    // Your init logic
  },
  loadingBuilder: (state) {
    final loadingData = state.loadingData;
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          CircularProgressIndicator(
            value: loadingData?.progress,
          ),
          if (loadingData?.stage != null)
            Text('Stage: ${loadingData!.stage}'),
        ],
      ),
    );
  },
  errorBuilder: (state) {
    return Center(
      child: Text('Error: ${state.errorData?.message ?? "Unknown"}'),
    );
  },
  initializedBuilder: (state) => YourMainApp(),
)

API Reference

CleanInitContainer

Parameter Type Required Description
init InitFunction Yes Async function that handles initialization
loadingWidget Widget? No Static widget shown during loading
loadingBuilder Widget Function(CleanInitState)? No Builder for loading state with access to state
errorWidget Widget? No Static widget shown on error
errorBuilder Widget Function(CleanInitState)? No Builder for error state with access to state
initializedWidget Widget? No* Static widget shown when initialized
initializedBuilder Widget Function(CleanInitState)? No* Builder for initialized state with access to state

Note: You must provide either initializedWidget OR initializedBuilder (but not both). For loading and error states, both widget and builder are optional, but you cannot provide both for the same state.

CleanInitState

States:

  • CleanInitState.loading - Initial loading state
  • CleanInitState.loadingWithData(LoadingData) - Loading with progress tracking
  • CleanInitState.initialized - Successfully initialized
  • CleanInitState.error(ErrorData) - Error state

LoadingData

LoadingData({
  double? progress,  // 0.0 to 1.0
  int? stage,        // Current stage number
})

ErrorData

ErrorData supports different error types with specialized handling:

// General error
ErrorData({
  required String message,
  ErrorType type = ErrorType.general,  // optional
})

// Or use convenience constructor
ErrorData.general('Error message')

// Version deprecated error (with additional version info)
ErrorData.versionDeprecated({
  required String currentVersion,
  required String minVersion,
  required String downloadUrl,
})

Error Types:

  • ErrorType.general - Standard initialization error
  • ErrorType.versionDeprecated - App version is outdated (includes VersionErrorData)
  • ErrorType.maintenance - App is under maintenance (includes MaintenanceData)

VersionErrorData (available when type == ErrorType.versionDeprecated):

class VersionErrorData {
  final String currentVersion;
  final String minVersion;
  final String downloadUrl;
}

MaintenanceData (available when type == ErrorType.maintenance):

class MaintenanceData {
  final DateTime? dueDate;  // Expected maintenance completion time
}

Example - Handling Different Error Types:

errorBuilder: (state) {
  final errorData = state.errorData;

  if (errorData?.type == ErrorType.versionDeprecated) {
    // Show custom update UI with download button
    return UpdateRequiredScreen(
      versionData: errorData!.versionData!,
    );
  }

  if (errorData?.type == ErrorType.maintenance) {
    // Show maintenance screen with optional due date
    return MaintenanceScreen(
      maintenanceData: errorData!.maintenanceData!,
      message: errorData.message,
    );
  }

  // Default error handling
  return ErrorScreen(message: errorData?.message ?? 'Unknown error');
},

Example - Setting Maintenance State:

// In your initialization logic
if (configProvider.isUnderMaintenance) {
  setInitState(CleanInitState.error(
    ErrorData.maintenance(
      message: 'We are currently performing scheduled maintenance',
      dueDate: DateTime(2025, 10, 20, 14, 0), // Optional
    ),
  ));
  return;
}

License

MIT

Libraries

clean_init