Just like the name suggest Top Level Function sits at the top of a class or file. And it should not be part of any class or method.
Now the best example is our main() which is also the entry point of flutter app. It's also not part of any class. So that's one way to do.
Now, we will take a look at another function which is also a top level function. This function we often see if we use Firebase push notification.
This is FirebaseMessaging.onBackgroundMessage(), which takes a handler. The handler must be a top a level function. That function must not be inside any other function or class.
Future<dynamic> myBackgroundMessageHandler(RemoteMessage message) async {
print("onBackground: ${message.notification?.title}/${message.notification?.body}/${message.notification?.titleLocKey}");
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(myBackgroundMessageHandler);
}
}catch(e) {}
runApp(MyApp());
}
From the above code we see myBackgroundMessageHandler() is a top level function since it's not part of any class and it's declared at the top of this main.dart file. Even at the top of main() function.
There's another way to make a function top level. Image you really you wanna put the above handler inside a class and enjoy the same benefit of a top level function.
We can do that using pragma
in dart. In that case we will put the above function inside a class and use like pragma at the top of the function
@pragma('vm:entry-point')
If you use pragma at the top of a function
it becomes like a top level function. Top level functions are accessed by native code of a platform.
@pragma('vm:entry-point')
static Future<void> myBackgroundMessageHandler(RemoteMessage message) async {
.........................................................
}
We still have to call myBackgroundMessageHandler() from FirebaseMessaging.onBackroundMessage()