Skip to content

Commit 6826fc0

Browse files
authored
Update _handlePushRouteInformation to Future<bool> to indicate whether any of the observer has handled the route or not (#147901)
follow up on comments on flutter/engine#52350
1 parent 8b129b9 commit 6826fc0

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

packages/flutter/lib/src/widgets/binding.dart

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -830,13 +830,14 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
830830
/// {@endtemplate}
831831
@protected
832832
@visibleForTesting
833-
Future<void> handlePopRoute() async {
833+
Future<bool> handlePopRoute() async {
834834
for (final WidgetsBindingObserver observer in List<WidgetsBindingObserver>.of(_observers)) {
835835
if (await observer.didPopRoute()) {
836-
return;
836+
return true;
837837
}
838838
}
839839
SystemNavigator.pop();
840+
return false;
840841
}
841842

842843
// The observer that is currently handling an active predictive back gesture.
@@ -870,7 +871,8 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
870871
// back gesture occurs but no predictive back route transition exists to
871872
// handle it. The back gesture should still cause normal pop even if it
872873
// doesn't cause a predictive transition.
873-
return handlePopRoute();
874+
await handlePopRoute();
875+
return;
874876
}
875877
_backGestureObserver?.handleCommitBackGesture();
876878
}
@@ -896,33 +898,36 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
896898
@protected
897899
@mustCallSuper
898900
@visibleForTesting
899-
Future<void> handlePushRoute(String route) async {
901+
Future<bool> handlePushRoute(String route) async {
900902
final RouteInformation routeInformation = RouteInformation(uri: Uri.parse(route));
901903
for (final WidgetsBindingObserver observer in List<WidgetsBindingObserver>.of(_observers)) {
902904
if (await observer.didPushRouteInformation(routeInformation)) {
903-
return;
905+
return true;
904906
}
905907
}
908+
return false;
906909
}
907910

908-
Future<void> _handlePushRouteInformation(Map<dynamic, dynamic> routeArguments) async {
911+
Future<bool> _handlePushRouteInformation(Map<dynamic, dynamic> routeArguments) async {
909912
final RouteInformation routeInformation = RouteInformation(
910913
uri: Uri.parse(routeArguments['location'] as String),
911914
state: routeArguments['state'] as Object?,
912915
);
913916
for (final WidgetsBindingObserver observer in List<WidgetsBindingObserver>.of(_observers)) {
914917
if (await observer.didPushRouteInformation(routeInformation)) {
915-
return;
918+
return true;
916919
}
917920
}
921+
return false;
918922
}
919923

920-
Future<dynamic> _handleNavigationInvocation(MethodCall methodCall) {
924+
Future<bool> _handleNavigationInvocation(MethodCall methodCall) {
921925
return switch (methodCall.method) {
922926
'popRoute' => handlePopRoute(),
923927
'pushRoute' => handlePushRoute(methodCall.arguments as String),
924928
'pushRouteInformation' => _handlePushRouteInformation(methodCall.arguments as Map<dynamic, dynamic>),
925-
_ => Future<dynamic>.value(),
929+
// Return false for unhandled method.
930+
_ => Future<bool>.value(false),
926931
};
927932
}
928933

packages/flutter/test/widgets/binding_test.dart

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,11 @@ void main() {
268268

269269
const String testRouteName = 'testRouteName';
270270
final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('pushRoute', testRouteName));
271-
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) {});
271+
final ByteData result = (await tester.binding.defaultBinaryMessenger
272+
.handlePlatformMessage('flutter/navigation', message, (_) {}))!;
273+
final bool decodedResult = const JSONMethodCodec().decodeEnvelope(result) as bool;
274+
275+
expect(decodedResult, true);
272276
expect(observer.pushedRoute, testRouteName);
273277

274278
WidgetsBinding.instance.removeObserver(observer);
@@ -286,8 +290,11 @@ void main() {
286290
final ByteData message = const JSONMethodCodec().encodeMethodCall(
287291
const MethodCall('pushRouteInformation', testRouteInformation),
288292
);
289-
await tester.binding.defaultBinaryMessenger
290-
.handlePlatformMessage('flutter/navigation', message, (_) {});
293+
final ByteData result = (await tester.binding.defaultBinaryMessenger
294+
.handlePlatformMessage('flutter/navigation', message, (_) {}))!;
295+
final bool decodedResult = const JSONMethodCodec().decodeEnvelope(result) as bool;
296+
297+
expect(decodedResult, true);
291298
expect(observer.pushedRoute, 'testRouteName');
292299
WidgetsBinding.instance.removeObserver(observer);
293300
});
@@ -377,6 +384,49 @@ void main() {
377384
WidgetsBinding.instance.removeObserver(observer);
378385
});
379386

387+
testWidgets('pushRouteInformation not handled by observer returns false', (WidgetTester tester) async {
388+
389+
const Map<String, dynamic> testRouteInformation = <String, dynamic>{
390+
'location': 'testRouteName',
391+
'state': null,
392+
};
393+
final ByteData message = const JSONMethodCodec().encodeMethodCall(
394+
const MethodCall('pushRouteInformation', testRouteInformation),
395+
);
396+
397+
final ByteData result = (await tester.binding.defaultBinaryMessenger
398+
.handlePlatformMessage('flutter/navigation', message, (_) {}))!;
399+
final bool decodedResult = const JSONMethodCodec().decodeEnvelope(result) as bool;
400+
401+
expect(decodedResult, false);
402+
});
403+
404+
testWidgets('pushRoute not handled by observer returns false', (WidgetTester tester) async {
405+
406+
const String testRoute = 'testRouteName';
407+
final ByteData message = const JSONMethodCodec().encodeMethodCall(
408+
const MethodCall('pushRoute', testRoute),
409+
);
410+
411+
final ByteData result = (await tester.binding.defaultBinaryMessenger
412+
.handlePlatformMessage('flutter/navigation', message, (_) {}))!;
413+
final bool decodedResult = const JSONMethodCodec().decodeEnvelope(result) as bool;
414+
415+
expect(decodedResult, false);
416+
});
417+
418+
419+
testWidgets('popRoute not handled by observer returns false', (WidgetTester tester) async {
420+
final ByteData message = const JSONMethodCodec().encodeMethodCall(
421+
const MethodCall('popRoute'),
422+
);
423+
424+
final ByteData result = (await tester.binding.defaultBinaryMessenger
425+
.handlePlatformMessage('flutter/navigation', message, (_) {}))!;
426+
final bool decodedResult = const JSONMethodCodec().decodeEnvelope(result) as bool;
427+
428+
expect(decodedResult, false);
429+
});
380430
testWidgets('Application lifecycle affects frame scheduling', (WidgetTester tester) async {
381431
expect(tester.binding.hasScheduledFrame, isFalse);
382432

0 commit comments

Comments
 (0)