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?
Solution 1:
You have to use it, in this way:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
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
Solution 2:
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.