skip to Main Content

I’m following a tutorial on a website to study flutter/dart. the tutorial techs me how to pass parameters (a Map) in named route through onGenerateRoute. now, I have created 2 webpage, say, main page and sub page, on my main page I created a button, if I clicked the button, it would route me to sub page with parameters. however, my program always stuck at error
======== Exception caught by widgets library =======================================================
The following _TypeError was thrown building Builder(dirty):
type ‘Null’ is not a subtype of type ‘Map<dynamic, dynamic>’

It’s frustrated after many attempts. I appreciate that if somebody can show root cause in detailed.
I’m using flutter 3.16.5, and dart is 3.2.3

I checked the variables

by print(settings); 
print(settings.arguments);           
print(settings.name);
it returns 
I/flutter ( 4675): RouteSettings("/subpage", {title: pass parameter in named route})
I/flutter ( 4675): {title: pass parameter in named route}
I/flutter ( 4675): /subpage

I don’t understand why the flutter still reported type error

below program for your reference:


//-----------------------------this is main page
import 'package:flutter/material.dart';
import 'package:firstapp/testsubpage.dart';

void main(){
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final Map routes={
    '/': (context) => const ShowPage(),
    '/subpage':(context,{arguments}) => SubPage(args: arguments,),
  };

  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
            useMaterial3:true,
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
            appBarTheme: const AppBarTheme(backgroundColor: Colors.blue)
        ),
//      home: const ShowPage()
        initialRoute: '/',
        onGenerateRoute:(RouteSettings settings){
          String? name=settings.name;
          Function pageContentBuilder = routes[name];
          if(pageContentBuilder != null){
            if(settings.arguments !=null){
              final Route route=MaterialPageRoute(builder: (context) => pageContentBuilder(settings.arguments));

              print(settings);
              print(settings.arguments);
              print(settings.name);

//              return MaterialPageRoute(builder: (context){
//                return pageContentBuilder('/subpage', settings.arguments);});
              return route;
            }else{
              final Route route=MaterialPageRoute(builder: (context)=>pageContentBuilder(context));
              return route;
            }
          }
          return null;
        }
    );
  }
}

class ShowPage extends StatefulWidget {
  const ShowPage({super.key});

  @override
  State<ShowPage> createState() => _ShowPageState();
}

class _ShowPageState extends State<ShowPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Named Route'),),
      body: Center(
          child: OutlinedButton(onPressed: () {
            Navigator.pushNamed(context, '/subpage', arguments: {'title':'pass parameter in named route'});
          }, child: const Text('Click Me'),)
      )
      ,
    );
  }
}


//-----this is sub page
import 'package:flutter/material.dart';

class SubPage extends StatefulWidget {
  final Map args;
  const SubPage({super.key, required this.args});
  @override
  State<SubPage> createState() => _SubPageState();
}

class _SubPageState extends State<SubPage> {

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title:  Text(widget.args['title']),),
      body: const Center(
        child: Text('This is sub page'),
      ),
    );
  }
}


2

Answers


  1. Chosen as BEST ANSWER

    Finally I found the error was in here: final Route route=MaterialPageRoute(builder: (context) => pageContentBuilder(settings.arguments));

    after changed it to final Route route=MaterialPageRoute(builder: (context) => pageContentBuilder(context, arguments:settings.arguments));

    the program is running normally.

    I supposed that I misunderstand this part:

    final Map routes={
    '/': (context) => const ShowPage(),
    '/subpage':(context,{arguments}) => SubPage(args: arguments,),};
    ...
    Function pageContentBuilder = routes[name];
    

  2. For the onGenerateRoute parameter, the example / my code is

    onGenerateRoute: (RouteSettings rs) { 
      Map<String, dynamic> args = {};
      if (rs.arguments != null) { 
        args = rs.arguments as Map<String, dynamic>;
      }
      return MaterialPageRoute<void>(
        settings: rs,
        builder: (BuildContext context) {
          switch (rs.name) { 
            case DiapositiveVideoFullplayView.routeName: 
              return DiapositiveVideoFullplayView(
                        settings: settings, 
                        videoId: args["videoId"], 
                        episodeId: args["episodeId"],
                    );
    
            case SettingsView.routeName: return SettingsView(settings: settings);
            case GeneralWebAccess.routeName: return GeneralWebAccess(url: args["url"]);
    
            default: return Container();
          }
        },
      );
    },
    

    When you push a new page, the arguments parameter will pass to that page, the follow is my code:

    var args = {"videoId": widget.videoId, "episodeId": widget.episodeId}; 
    Navigator.pushNamed(
        context, 
        DiapositiveVideoFullplayView.routeName, 
        arguments: args,
    );
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search