【问题标题】:Flutter ignores return statement inside of "if" branchFlutter 忽略“if”分支内的 return 语句
【发布时间】:2021-02-10 07:27:53
【问题描述】:

我正在尝试使用 PopupMenuButton 小部件从对象列表中创建过滤器。我认为逻辑是合理的,但 Flutter/Dart 似乎忽略了下面代码块中名为“fliterFavs”的函数中“if 分支”中的 return 语句。

当我选择“Favs”时,它会按预期进行识别,并且返回之前的打印语句工作正常。

当我使用相同的 return 语句代替“if 语句”之外的那个时,它可以正常工作。我得到了我期望的过滤数据集。

我什至尝试将它作为两个背靠背的 if 语句,而不是您在下面看到的嵌套语句。还是不行。

有什么想法吗?

final List<Product> favProducts = [];

  Widget filterFavs(value) {
    loadedProducts.forEach((i) {
      if (i.isFavorite == true) {
        favProducts.add(i);
        if (value == "Favs") {
          print(value);
          return buildGrid(favProducts);
        }
      }
    });
    return buildGrid(loadedProducts);
  }

  Widget buildGrid(List newList) {
    return GridView.builder(
      padding: const EdgeInsets.all(10.0),
      itemCount: newList.length,
      itemBuilder: (ctx, i) => ProductItem(
        newList[i].id,
        newList[i].title,
        newList[i].imageUrl,
      ),
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 3 / 2,
        crossAxisSpacing: 10,
        mainAxisSpacing: 10,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('MyShop'),
          actions: <Widget>[
            PopupMenuButton(
              onSelected: (val) {
                filterFavs(val);
              },
              icon: Icon(
                Icons.more_vert,
              ),
              itemBuilder: (context) => [
                PopupMenuItem(
                  child: Text("Favs"),
                  value: "Favs",
                ),
                PopupMenuItem(
                  child: Text("All"),
                  value: "All",
                ),
              ],
            ),
          ],
        ),
        //use a filter on the item builder
        body: filterFavs(context));
  }
}

【问题讨论】:

    标签: flutter if-statement dart return


    【解决方案1】:

    想想你所指的 return 是从哪个函数返回的。它返回到传递给forEach 方法的匿名函数,而不是像您期望的那样传递给filterFavs。这不是颤振/飞镖的问题,而是您的期望的问题。

    您可以使用替代的 for-each 语法来解决这个问题:

    Widget filterFavs(value) {
      for(var i in loadedProducts) {
        if (i.isFavorite == true) {
          favProducts.add(i);
          if (value == "Favs") {
            print(value);
            return buildGrid(favProducts);
          }
        }
      }
      return buildGrid(loadedProducts);
    }
    

    【讨论】:

    • 感谢您的快速回复。似乎合乎逻辑。它仍然不起作用。相同的行为
    • @ctacta1 “不起作用”是什么意思?我很难相信它们会有相同的行为。
    • 相同的结果...我通过 PopupMenuItem 通过 'more_vert' 图标在 appBar 中选择“Favs”... 从 print 方法返回“Favs”,但页面仍然呈现“ ALL”实例,而不是只有那些“i.isFavorite == true”...所以继续返回:return buildGrid(loadedProducts);而不是返回 buildGrid(favProducts);显然我的代码还有其他问题
    • @ctacta1 你使用这个方法很奇怪。你为什么要body: filterFavs(context)
    • 当我现在看到它时,这是一个很好的问题。我想我的问题就在那里。我要做的就是创建一个过滤器,用户可以在其中使用他/她返回的产品子集。但似乎 body 属性没有看到 buildGrid() 的输出。不知道。
    【解决方案2】:

    Christopher Moore 感谢您的帮助,这是现在可行的最终解决方案。

    import 'package:flutter/material.dart';
    
    import '../models/product.dart';
    import '../widgets/product_item.dart';
    
    class ProductsOverviewScreen extends StatefulWidget {
      @override
      _ProductsOverviewScreenState createState() => _ProductsOverviewScreenState();
    }
    
    class _ProductsOverviewScreenState extends State<ProductsOverviewScreen> {
      List choices = ["Favs", "All"];
      String _choice = '';
    
      void _select(userChoice) {
        setState(() {
          _choice = userChoice;
          print(_choice);
        });
      }
    
      final List<Product> loadedProducts = [
        Product(
          id: 'p1',
          title: 'Red Shirt',
          description: 'A red shirt - it is pretty red!',
          price: 29.99,
          isFavorite: true,
          imageUrl:
              'https://cdn.pixabay.com/photo/2016/10/02/22/17/red-t-shirt-1710578_1280.jpg',
        ),
        Product(
          id: 'p2',
          title: 'Trousers',
          description: 'A nice pair of trousers.',
          price: 59.99,
          isFavorite: true,
          imageUrl:
              'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Trousers%2C_dress_%28AM_1960.022-8%29.jpg/512px-Trousers%2C_dress_%28AM_1960.022-8%29.jpg',
        ),
        Product(
          id: 'p3',
          title: 'Yellow Scarf',
          description: 'Warm and cozy - exactly what you need for the winter.',
          price: 19.99,
          isFavorite: false,
          imageUrl:
              'https://live.staticflickr.com/4043/4438260868_cc79b3369d_z.jpg',
        ),
        Product(
          id: 'p4',
          title: 'A Pan',
          description: 'Prepare any meal you want.',
          price: 49.99,
          isFavorite: false,
          imageUrl:
              'https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Cast-Iron-Pan.jpg/1024px-Cast-Iron-Pan.jpg',
        ),
      ];
    
      List<Product> favProducts = [];
    
      Widget filterFavs(value) {
        if (favProducts.isEmpty) {
          // this is to prevent items from being infinitely added to favProducts
          //if user selects Favs more than once
          for (var i in loadedProducts) {
            if (i.isFavorite == true) {
              favProducts.add(i);
            }
          }
        }
        if (value == "Favs") {
          print(value);
          return buildGrid(favProducts);
        }
        favProducts = [];
        return buildGrid(loadedProducts);
      }
    
      Widget buildGrid(List newList) {
        return GridView.builder(
          padding: const EdgeInsets.all(10.0),
          itemCount: newList.length,
          itemBuilder: (ctx, i) => ProductItem(
            newList[i].id,
            newList[i].title,
            newList[i].imageUrl,
          ),
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            childAspectRatio: 3 / 2,
            crossAxisSpacing: 10,
            mainAxisSpacing: 10,
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text('MyShop'),
              actions: <Widget>[
                PopupMenuButton(
                    elevation: 3.2,
                    initialValue: choices[1],
                    onSelected: _select,
                    icon: Icon(
                      Icons.more_vert,
                    ),
                    itemBuilder: (context) => [
                          PopupMenuItem(
                            child: Text(choices[0]),
                            value: choices[0],
                          ),
                          PopupMenuItem(
                            child: Text(choices[1]),
                            value: choices[1],
                          ),
                        ]),
              ],
            ),
            //use a filter on the item builder
            body: filterFavs(_choice));
      }
    }
    
    
    

    【讨论】:

      猜你喜欢
      • 2016-06-07
      • 1970-01-01
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 2016-01-16
      • 2017-02-05
      • 2020-10-28
      • 2015-08-13
      相关资源
      最近更新 更多