Search code examples
androidflutterdartmobile

Where is the correct place to start application initialization in flutter?


The project has a lot of initial initialization, without which the project will not work (logging, database initialization (floor), getIt (services), and a bunch more)

I can put all this friendly initialization into one method, let's call it initApp()

Where is the right place to run it?

My options:

  1. In the main method, actually before runApp
void main() {
  initApp();
  runApp(const MyApp());
}
  1. Make the first home_screen, in which initialization will take place, and after initialization, transfer it to the desired screen depending on the user authentication and user role (although this processing can also be done in go_router). Minuses item 2, using go_router, deeplink does not work well, because we actually do not get to the home_screen
void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  
  @override
  void initState() {
    super.initState();
    initApp();
    FlutterNativeSplash.remove(); // end splash
  }
  
  @override
  Widget build(BuildContext context) {
    return NextScreenForAuth();
  }
}
  1. Any other correct solution?

Solution

  • The correct way is to follow the instructions from each package that you need to initialize.

    For example, the FlutterFire docs tells you to put the initialization inside the main method:

    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      runApp(MyApp());
    }
    

    You can also see the package's example app. For example, get_it has the initialization done like this in its example app:

    GetIt getIt = GetIt.instance;
    
    void main() {
      getIt.registerSingleton<AppModel>(AppModelImplementation(),
          signalsReady: true);
    
      runApp(const MyApp());
    }
    

    If you have multiple initializations that are asynchronous and are independent from each other, you can wrap them with a Future.wait (or use the wait extension on the list):

    await Future.wait(
        [
          Hive.initFlutter(),
          dotenv.load(fileName: '.env'),
        ],
      );