Initialize Flutter App with async operations & in-app locale retrieval while playing startup video

21 Views Asked by At

Let's say you have a Flutter App that you initialize using sth like:

void main() {
  /// Required to assure that locking the device orientation and then running
  /// the app works as intended
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((fn) {
    runApp(
      /// Riverpod being used
      const ProviderScope(
        child: MyApp(),
      ),
    );
  });
}

You want the sequence of bootup processes to be:

  1. Load and launch a lottie animation video of your brand, using this package and sth like:
Lottie.asset(
            'assets/splash.json',
            controller: _controller,
            onLoaded: (composition) {
              /// As soon as the lottie video has finished loading, start
              /// playing it
              _controller
                ..duration = composition.duration
                ..forward();

              /// Do whatever you have to initialize here in the background, while the 
              /// video is playing
            },
          )
  1. As shown in the code above, you want to execute some kind of startup processes in the background, while the lottie video is playing (e.g. retrieve some values from the shared preferences, execute fast HTTP Requests, etc.). For example, the user must be able to change the mobile app's language within the mobile app itself. This comes with the fact that, if the user previously set a preferred language within the Shared Preferences storage (to survive app reboot), its retrieval is asynchronous.
  2. As soon as the video concludes, and your code assures that all of your asynchronous operations have been finished with the according awaits, launch your app's actual MaterialApp / CupertinoApp widget.

To be able to do what I want, I first thought of calling runApp() twice, but the problem with this is that my startup code initializes riverpod stuff, and the ProviderScope is limited to a single runApp() scope, according to the docs.

So to reach what I want, I thought of :

  1. Initializing the app in main() with sth like runApp(Center(child: MyLottieAnimation())), with MyLottieAnimation() being a Center() widget holding the Lottie.asset() widget shown above as child (so no MaterialApp or CupertinoApp widget at the very start).
  2. When the animation and the tasks executed in the background conclude, call Navigator.of(context).pushReplacement(), yielding the root MaterialApp() widget.
  3. That root MaterialApp() widget is actually a ConsumerStatefulWidget(), listening to changes to the locale in-app via sth like ref.watch(inAppLocaleProvider); within its build method (and thus rebuilding whenever that value changes, by adapting the locale property of the according MaterialApp).

For this to work, I wanted to ask:

A) Are there risks coming from calling runApp() not returning any of MaterialApp or CupertinoApp at the beginning ? The docs say that MaterialApp is required for specific widgets of the Material Design to Work properly. But is this risk flutter-specific, or device-specific? E.g. when I run my Flutter app in the above-mentioned way on a random testing device and flutter reports no error, is there any chance that the app bootup may fail for some devices, due to the initial root widget not being MaterialApp or CupertinoApp ?

B) If it turns out that the outermost widget must be a MaterialApp widget, is it possible to initiate the app with a MaterialApp widget wrapping the lottie animation, which at its end transitions to another MaterialApp widget using pushReplacement, as mentioned above? I know you should only have a single MaterialApp widget per app, but what if one you use replaces the other in that way ?

C) Could it become a problem to re-build the outermost MaterialApp() widget upon a locale change ? Should you rather maybe provide a static locale to the MaterialApp's locale property, and provide a Localizations.override() widget as the home widget of it, and listen to locale changes only there ?

0

There are 0 best solutions below