Search code examples
flutterdartnull-safety

Dart closure return type problem after migrating to null safety


The below code used to work before migrating to Flutter 2 and null safety. I just can't figure out what the correct return type should be. The error I get is:

The return type 'List<PopupMenuItem<dynamic>?>' isn't a 'List<PopupMenuEntry<dynamic>>', as required by the closure's context.

And the code is:

 Widget _parentMenuSelector() {
    return PopupMenuButton<dynamic>(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Icon(Icons.content_copy),
            Text('Copy to another menu'),
          ],
        ),
      ),
      onSelected: (dynamic selectedMenu) {
        Map<String, dynamic> selMenu = selectedMenu;
        print(selMenu['id']);
        model!.copyMenuItem(selMenu['id']);
      },
      itemBuilder: (BuildContext context) {
        return model!.restaurant!.restaurantMenus!.values.map((dynamic item) { //ERROR
          Map<String, dynamic> itemMap = item;                                 //ERROR
          if (itemMap['name'] != model!.menu!.name) {                          //ERROR
            return PopupMenuItem<dynamic>(                                     //ERROR
              child: Text('Copy to ${itemMap['name']}'),                       //ERROR
              value: item,                                                     //ERROR
            );                                                                 //ERROR
          }                                                                    //ERROR
        }).toList();                                                           //ERROR
      },
    );
  }

Solution

  • As suggested by jamesdlin, here's what worked for me at least syntactically for now. I'm not sure yet if it's going to work functionally - I haven't build the app yet as I'm still fixing null-safety migration issues.

      Widget _parentMenuSelector() {
        return PopupMenuButton<dynamic>(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Icon(Icons.content_copy),
                Text('Copy to another menu'),
              ],
            ),
          ),
          onSelected: (dynamic selectedMenu) {
            Map<String, dynamic> selMenu = selectedMenu;
            print(selMenu['id']);
            model!.copyMenuItem(selMenu['id']);
          },
          itemBuilder: (BuildContext context) {
            return model!.restaurant!.restaurantMenus!.values.map((dynamic item) {
              Map<String, dynamic> itemMap = item;
              if (itemMap['name'] != model!.menu!.name) {
                return PopupMenuItem<dynamic>(
                  child: Text('Copy to ${itemMap['name']}'),
                  value: item,
                );
              } else {
                return PopupMenuItem<dynamic>(
                  child: null,
                );
              }
            }).toList();
          },
        );
      }