-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Use case
If a developer wants to call runApp within a custom Zone with zoneValues and the zoneValues rely on the underlying platform, they must call WidgetsFlutterBinding.ensureInitialized() like:
final token = Object();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final value = await _getPlatformValue();
runZoned(
() => runApp(MyApp()),
zoneValues: {token: value},
);
}This appears to work as expected, however, because WidgetsFlutterBinding also initializes other bindings like GestureBinding the zoneValue is not accessible within onPressed callbacks:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(Zone.current[token]); // OK
return MaterialApp(
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
print(Zone.current[token]); // NULL
},
child: Text('Click Me'),
),
),
),
);
}
}Proposal
It would be great to have a way to initialize the ServicesBinding and SchedulerBinding independently of the remaining bindings in order to support accessing data from the underlying platform before runApp but without initializing the WidgetsBinding.instance within the root zone.
final token = Object();
void main() async {
FlutterServicesBinding.ensureInitialized();
final value = await _getPlatformValue();
runZoned(
() => runApp(MyApp()),
zoneValues: {token: value},
);
}class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(Zone.current[token]); // OK
return MaterialApp(
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
print(Zone.current[token]); // OK
},
child: Text('Click Me'),
),
),
),
);
}
}Where FlutterServicesBinding could look something like:
FlutterServicesBinding Sample
import 'dart:ui' as ui show SingletonFlutterWindow, PlatformDispatcher, window;
import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
class FlutterServicesBinding extends _StandaloneBindingBase
with SchedulerBinding, ServicesBinding {
FlutterServicesBinding._();
static FlutterServicesBinding? _instance;
static FlutterServicesBinding ensureInitialized() {
return _instance ??= FlutterServicesBinding._();
}
}
abstract class _StandaloneBindingBase implements BindingBase {
_StandaloneBindingBase() {
initInstances();
window.onReportTimings = null;
}
@override
ui.SingletonFlutterWindow get window => ui.window;
@override
ui.PlatformDispatcher get platformDispatcher {
return ui.PlatformDispatcher.instance;
}
@override
@protected
@mustCallSuper
void initInstances() {}
@override
@protected
@mustCallSuper
void initServiceExtensions() {}
@override
@protected
bool get locked => false;
@override
@protected
Future<void> lockEvents(Future<void> Function() callback) async {}
@override
@protected
@mustCallSuper
void unlocked() {}
@override
Future<void> reassembleApplication() async {}
@override
@mustCallSuper
@protected
Future<void> performReassemble() async {}
@override
@protected
void registerSignalServiceExtension({
required String name,
required AsyncCallback callback,
}) {}
@override
@protected
void registerBoolServiceExtension({
required String name,
required AsyncValueGetter<bool> getter,
required AsyncValueSetter<bool> setter,
}) {}
@override
@protected
void registerNumericServiceExtension({
required String name,
required AsyncValueGetter<double> getter,
required AsyncValueSetter<double> setter,
}) {}
@override
@protected
void postEvent(String eventKind, Map<String, dynamic> eventData) {}
@override
@protected
void registerStringServiceExtension({
required String name,
required AsyncValueGetter<String> getter,
required AsyncValueSetter<String> setter,
}) {}
@override
@protected
void registerServiceExtension({
required String name,
required ServiceExtensionCallback callback,
}) {}
@override
String toString() => '<${objectRuntimeType(this, 'BindingBase')}>';
}DartPad Demos
-
DartPad illustrating the limitation when using
WidgetsFlutterBinding.ensureInitialized(); -
DartPad illustrating an example of how this can be improved via
FlutterServicesBinding.ensureInitialized();
Additional Info
Published https://pub.dev/packages/flutter_services_binding as a workaround in the meantime.