151

I am trying to use the Firebase package with the below line of code.

I really want to know what this line of code actually does?

The official documentation didn't help me much. Can someone explain me, please?

Code snippet

MendelG
  • 14,885
  • 4
  • 25
  • 52
Abhishek Ghimire
  • 1,826
  • 2
  • 8
  • 11

3 Answers3

174

You have to use it, in this way:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

enter image description here

https://flutter.dev/docs/resources/architectural-overview#architectural-layers

The above image is the architecture layers of Flutter, the WidgetFlutterBinding is used to interact with the Flutter engine. Firebase.initializeApp() needs to call native code to initialize Firebase, and since the plugin needs to use platform channels to call the native code, which is done asynchronously therefore you have to call ensureInitialized() to make sure that you have an instance of the WidgetsBinding.

From the docs:

Returns an instance of the WidgetsBinding, creating and initializing it if necessary. If one is created, it will be a WidgetsFlutterBinding. If one was previously initialized, then it will at least implement WidgetsBinding.

You only need to call this method if you need the binding to be initialized before calling runApp.


From the source code:

  @override
  Future<FirebaseAppPlatform> initializeApp(
      {String name, FirebaseOptions options}) async {
    if (name == defaultFirebaseAppName) {
      throw noDefaultAppInitialization();
    }

    // Ensure that core has been initialized on the first usage of
    // initializeApp
    if (!isCoreInitialized) {
      await _initializeCore();
    }

    // If no name is provided, attempt to get the default Firebase app instance.
    // If no instance is available, the user has not set up Firebase correctly for
    // their platform.
    if (name == null) {
      MethodChannelFirebaseApp defaultApp =
          appInstances[defaultFirebaseAppName];

      if (defaultApp == null) {
        throw coreNotInitialized();
      }

      return appInstances[defaultFirebaseAppName];
    }

    assert(options != null,
        "FirebaseOptions cannot be null when creating a secondary Firebase app.");

    // Check whether the app has already been initialized
    if (appInstances.containsKey(name)) {
      throw duplicateApp(name);
    }

    _initializeFirebaseAppFromMap(await channel.invokeMapMethod(
      'Firebase#initializeApp',
      <String, dynamic>{'appName': name, 'options': options.asMap},
    ));

    return appInstances[name];
  }

The invokeMapMethod will invoke a method on the above channel with the specified arguments, which will then call the initializeApp() method in the native code, https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java#L227


There are also different ways to initialize Firebase, which you can check here:

No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() in Flutter and Firebase

In the other ways we do not call WidgetsFlutterBinding.ensureInitialized() since the runApp() function calls it internally:

void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}

https://github.com/flutter/flutter/blob/bbfbf1770c/packages/flutter/lib/src/widgets/binding.dart#L1012

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • 1
    According to your last answer, we don't need to call this function anymore!? – gausoft Apr 27 '22 at 12:37
  • @gausoft you have to call it,*In the other ways we do not call WidgetsFlutterBinding.ensureInitialized() since the runApp() function calls it internally*, if you check the link I provided, there are 4 different ways to use Firebase, if you check *First Example* in that link, I don't call `WidgetsFlutterBinding.ensureInitialized()` because it is called internally in the `runApp()` – Peter Haddad Apr 27 '22 at 13:13
60

A simple answer is that if Flutter needs to call native code before calling runApp

WidgetsFlutterBinding.ensureInitialized();

makes sure that you have an instance of the WidgetsBinding, which is required to use platform channels to call the native code.

You only need to call this method if you need the binding to be initialized before calling runApp.

Javeed Ishaq
  • 6,024
  • 6
  • 41
  • 60
21

A simple answer, you need to use this line, if your main function uses async keyword because you use await statement inside it.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferences prefs = await SharedPreferences.getInstance(); // just an example
}
Mostafa Mahmoud
  • 541
  • 3
  • 7