#flutter #if-statement #dart #return
#flutter #if-statement #dart #Возврат
Вопрос:
Я пытаюсь создать фильтр из списка объектов, используя виджет PopupMenuButton. Я думаю, что логика правильная, но Flutter / Dart, похоже, игнорирует оператор return внутри ветки «if» в моей функции с именем «fliterFavs» в приведенном ниже фрагменте кода.
Когда я выбираю «Избранное», оно распознается как ожидалось, и оператор печати перед возвратом работает нормально.
Когда я использую тот же самый оператор return вместо того, который находится вне оператора 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));
}
}
Ответ №1:
Подумайте о функции, из которой возвращается возврат, на который вы ссылаетесь. Он возвращается к анонимной функции, переданной forEach
методу, а не filterFavs
так, как вы ожидаете. Это не проблема с flutter / dart, это проблема с вашими ожиданиями.
Вы можете использовать альтернативный синтаксис 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);
}
Комментарии:
1. Спасибо за быстрый ответ. Кажется логичным. Он по-прежнему не работает. То же поведение
2. @ctacta1 Что значит «не работает»? Мне очень трудно поверить, что они будут иметь одинаковое поведение.
3. Тот же результат… Я выбираю «Избранное» через PopupMenuItem через значок «more_vert» на панели приложений… «Favs» возвращается из метода print, но страница по-прежнему отображает «ВСЕ» экземпляры, а НЕ ТОЛЬКО те, где «i.isFavorite == true»… таким образом, продолжает возвращаться: return buildGrid(loadedProducts); вместо return buildGrid(favProducts); Очевидно, что в моем коде что-то еще не так
4. @ctacta1 Вы используете этот метод очень странно. Почему вы делаете
body: filterFavs(context)
5. Как я сейчас смотрю на это, это отличный вопрос. Я думаю, что моя проблема заключается в этом. Все, что я пытаюсь сделать, это создать фильтр, в котором пользователь может использовать подмножество продуктов, которые он / она получает для возврата. Но похоже, что свойство body не видит вывод buildGrid() . Не знаю.
Ответ №2:
Кристофер Мур спасибо за вашу помощь, вот окончательное решение, которое теперь работает.
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,_dress_(AM_1960.022-8).jpg/512px-Trousers,_dress_(AM_1960.022-8).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));
}
}