Repository: flutter
Issue: When a frame has already been shown, a black flash occurs when async localization delegates are involved in MaterialApp
Labels: framework,f: material design,has reproducible steps,found in release: 2.2,team-design,triaged-design

<details>
  <summary>Minimal Repro</summary>


```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() => runApp(AppRoot());

class AppRoot extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<bool>(
      // Transition from green -> blue after 3 seconds.
      future: Future.delayed(const Duration(seconds: 3)).then((_) => true),
      builder: (context, snapshot) =>
          // Show a green container first at the first frame.
          !snapshot.hasData ? Container(color: Colors.green) : MyApp(),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: const [SlowLocalizationsDelegate()],
      home: Container(color: Colors.blue),
    );
  }
}

class MyAppLocalizations {}

class SlowLocalizationsDelegate
    extends LocalizationsDelegate<MyAppLocalizations> {
  const SlowLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => true;

  @override
  Future<MyAppLocalizations> load(Locale locale) {
    // Using a [SynchronousFuture] doesn't cause the black flash, because this
    // flow [1] is reached instead and the empty [Container] causing the black
    // flash is *not* shown [2].
    //
    // [1]: https://github.com/flutter/flutter/blob/6876c52b5ba7305bd9107f5b701f80ca6c3bd254/packages/flutter/lib/src/widgets/localizations.dart#L540
    // [2]: https://github.com/flutter/flutter/blob/6876c52b5ba7305bd9107f5b701f80ca6c3bd254/packages/flutter/lib/src/widgets/localizations.dart#L573-L574
    //
    // return SynchronousFuture(MyAppLocalizations());

    return Future.value(MyAppLocalizations());
  }

  @override
  bool shouldReload(SlowLocalizationsDelegate old) => false;
}

```

```
Flutter 2.5.0-2.0.pre.154 • channel unknown • unknown source
Framework • revision 675135a2e8 (5 days ago) • 2021-08-03 19:15:05 -0700
Engine • revision ae8071be20
Tools • Dart 2.14.0 (build 2.14.0-377.0.dev)
```

</details>

Expected on app launch:

```
green -> blue
```

Actual:

```
green -> black -> blue
```

This is because there are two methods of loading localizations under the hood of `MaterialApp` - synchronous and asynchronous depending on how `LocalizationsDelegate.load` is implemented. When this is asynchronous, the first frame is [deferred](https://github.com/flutter/flutter/blob/6876c52b5ba7305bd9107f5b701f80ca6c3bd254/packages/flutter/lib/src/widgets/localizations.dart#L542-L546), and an [empty `Container`](https://github.com/flutter/flutter/blob/6876c52b5ba7305bd9107f5b701f80ca6c3bd254/packages/flutter/lib/src/widgets/localizations.dart#L573-L574) is built but not shown on screen.

Normally, this would not be a problem when the `MaterialApp` is at the root of the widget tree. However, certain apps may want to show another frame / widget tree before transitioning to this `MaterialApp` containing the localization delegates. Since the first frame has already been shown, calls to `deferFirstFrame` [do nothing](https://github.com/flutter/flutter/blob/f4abaa0735eba4dfd8f33f73363911d63931fe03/packages/flutter/lib/src/rendering/binding.dart#L371-L372), and there is a short while when the empty `Container` is shown on screen, causing the black flash.

A potential solution could be to have some sort of `deferNextFrame` API instead of `deferFirstFrame` that allows the async load to happen at anytime after the first frame has been shown, without actually showing the empty `Container` on screen.

Internal context: b/185066490