1

I have a Flutter app in which I'm trying to dive deeper into routing. When I use the home property within my MaterialApp widget, it seems to be perfectly happy. As soon as I change it to use initialRoute, the app crashes with a NoSuchMethodError and an error that says The builder for route '/' returned null - my initial route is '/loading'.

Errors:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building Builder(dirty):
Closure call with mismatched arguments: function 'new MyApp.<anonymous closure>'
Receiver: Closure: (BuildContext) => LoadingScreen
Tried calling: new MyApp.<anonymous closure>(Instance of 'StatelessElement', null)
Found: new MyApp.<anonymous closure>(BuildContext) => LoadingScreen

The relevant error-causing widget was: 
  MaterialApp file:///Users/tanner/Documents/Coding/Courses/AppBrewery/Flutter/Clima-Flutter/lib/main.dart:18:12
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1      MyApp._buildRoute (package:clima/main.dart:54:30)
#2      MyApp._makeRoute (package:clima/main.dart:43:26)
#3      MyApp._generateRoute.<anonymous closure> (package:clima/main.dart:27:42)
#4      MaterialPageRoute.buildPage (package:flutter/src/material/page.dart:87:27)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The builder for route "/" returned null.
The relevant error-causing widget was: 
  MaterialApp file:///Users/tanner/Documents/Coding/Courses/AppBrewery/Flutter/Clima-Flutter/lib/main.dart:18:12
════════════════════════════════════════════════════════════════════════════════════════════════════

My Routing Weirdness

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final Map<String, Function> _routes = {
    '/loading': (BuildContext context, LoadingScreenArguments args) =>
        LoadingScreen(args),
    '/location': (BuildContext context, LocationScreenArguments args) =>
        LocationScreen(args),
  };

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
//      home: LoadingScreen(),
      initialRoute: '/loading',
      onGenerateRoute: _generateRoute,
    );
  }

  MaterialPageRoute _generateRoute(RouteSettings settings) {
    return MaterialPageRoute(
      builder: (BuildContext context) => _makeRoute(
        context: context,
        routeName: settings.name,
        arguments: settings.arguments,
      ),
      maintainState: true,
      fullscreenDialog: false,
    );
  }

  Widget _makeRoute({
    @required BuildContext context,
    @required String routeName,
    Object arguments,
  }) {
    final Widget child = _buildRoute(
        context: context, routeName: routeName, arguments: arguments);
    return child;
  }

  Widget _buildRoute({
    @required BuildContext context,
    @required String routeName,
    Object arguments,
  }) {
    print(routeName);
    return _routes[routeName](context, arguments);
  }
}
5
  • change /loading to loading - now it tries to create two routes: / and /loading Commented Apr 20, 2020 at 3:42
  • @pskink - That worked!! Why would it try to create both / and /loading? Does the Navigator try to match using pattern matching similar to a web app and so it will attempt to match any / before /**? Commented Apr 20, 2020 at 14:44
  • That's a huge help! If you submit this as an answer, I'll accept it as the correct one! Commented Apr 20, 2020 at 14:48
  • feel free to write a self answer ;-) Commented Apr 20, 2020 at 14:48
  • btw you could also use MaterilApp.onGenerateInitialRoutes but its a rather new feature... Commented Apr 20, 2020 at 15:36

2 Answers 2

4

Thanks to the comment on my answer by @pskink, the solution is pretty apparent: Removing the leading / solves the problem.

This comment in the source code reveals that the Navigator will split the string on / characters and loads the route for each chunk in order to preserve a traceable history.

Sign up to request clarification or add additional context in comments.

Comments

0

It's because it can't find any route named '/loading', because you have made a route map of <String, Function> whereas routes are WidgetBuilder's.

So try replacing:

Map<String, Function>

with:

Map<String, WidgetBuilder>

1 Comment

This throws lint errors because it doesn't want me to pass the arguments object down to the widget. Any thoughts?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.