Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Does WidgetsFlutterBinding.ensureInitialized() do?

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

like image 337
Abhishek Ghimire Avatar asked Sep 13 '20 16:09

Abhishek Ghimire


3 Answers

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

like image 116
Peter Haddad Avatar answered Nov 12 '22 19:11

Peter Haddad


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.

like image 37
Javeed Ishaq Avatar answered Nov 12 '22 18:11

Javeed Ishaq


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
}
like image 13
Mostafa Mahmoud Avatar answered Nov 12 '22 18:11

Mostafa Mahmoud