notifyListeners 后列表被清空
List is emptied after notifyListeners
我有一个怪怪的,一直摸不着头脑
我有一个 属性 在我的一个 class 上使用提供商
除了这种特殊情况,我可以很好地访问和修改:
我将产品添加到 _products 列表
_products.add(product);
notifyListeners();
此时产品是 class 具有以下属性
name String;
id String;
ingredients List<String>;
假设产品是
final product = Product(name:'milk', id:1, ingredients:['milk']);
这个元素被添加到列表中,我可以在调试中看到现在 _products 确实是一个列表,里面有 1 个项目并且所有属性都是正确的
一旦它通知听众他们获得了 _products 的新值,我可以看到他们收到新值就好了,除了由于某些奇怪的原因成分列表是空的!
[ Product(name:'milk', id:1, ingredients:[]) ] // _products for representation purposes
我只是在通知之前验证了 _products 的值,它的成分 属性 正确,然后在通知之后,属性 变成了一个空列表
其他 2 个属性 id 和 name 已正确更新
我已经非常彻底地检查过了,我没有代码可以修改 _products 其他地方
由于我们不知道您对 Product 和 ProductList 的实现细节,因此我在这种情况下自己创建了一个示例。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Product
{
final String name;
final String id;
final List<String> ingredients;
const Product({
required this.name,
required this.id,
required this.ingredients
});
}
class ProductList extends ChangeNotifier
{
final _products = <Product>[];
void add(Product product)
{
_products.add(product);
notifyListeners();
}
Iterable<Product> get products => _products;
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ProductList()),
],
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _incrementCounter() {
context.read<ProductList>().add(const Product(name: 'Product 1', id: '1234', ingredients: ['Hello', 'There']));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: const SafeArea(
child: Products(),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class Products extends StatelessWidget {
const Products({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for(var product in context.watch<ProductList>().products)
ListTile(
leading: Text(product.id),
title: Text(product.name),
subtitle: Text(product.ingredients.join(', ')),
),
]
);
}
}
您可以在Dart Pad. Hope this helps. Please refer to How to create a Minimal, Reproducible Example上查看。
抱歉,这根本不是提供商的问题
发生的事情是,当我将产品分配给产品列表时,成分列表是一个参考,在使用后被控制器清除,所以在代码中是这样的:
List<String> ingredients = [];
void onAddIngredient(){
ingredients.add(ingredientController.text);
}
void onSubmit(){
final myNewProduct = Product(
name: nameController.text,
id: idController.text,
ingredients:ingredients
)
providerAction(myNewProduct); // This is where it gets added to _products
nameController.clear();
idController.clear();
ingredientController.clear();
ingredients.clear(); // This was the problem where I was deleting the reference
}
我有一个怪怪的,一直摸不着头脑
我有一个 属性 在我的一个 class 上使用提供商 除了这种特殊情况,我可以很好地访问和修改:
我将产品添加到 _products 列表
_products.add(product);
notifyListeners();
此时产品是 class 具有以下属性
name String;
id String;
ingredients List<String>;
假设产品是
final product = Product(name:'milk', id:1, ingredients:['milk']);
这个元素被添加到列表中,我可以在调试中看到现在 _products 确实是一个列表,里面有 1 个项目并且所有属性都是正确的
一旦它通知听众他们获得了 _products 的新值,我可以看到他们收到新值就好了,除了由于某些奇怪的原因成分列表是空的!
[ Product(name:'milk', id:1, ingredients:[]) ] // _products for representation purposes
我只是在通知之前验证了 _products 的值,它的成分 属性 正确,然后在通知之后,属性 变成了一个空列表 其他 2 个属性 id 和 name 已正确更新
我已经非常彻底地检查过了,我没有代码可以修改 _products 其他地方
由于我们不知道您对 Product 和 ProductList 的实现细节,因此我在这种情况下自己创建了一个示例。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Product
{
final String name;
final String id;
final List<String> ingredients;
const Product({
required this.name,
required this.id,
required this.ingredients
});
}
class ProductList extends ChangeNotifier
{
final _products = <Product>[];
void add(Product product)
{
_products.add(product);
notifyListeners();
}
Iterable<Product> get products => _products;
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ProductList()),
],
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _incrementCounter() {
context.read<ProductList>().add(const Product(name: 'Product 1', id: '1234', ingredients: ['Hello', 'There']));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: const SafeArea(
child: Products(),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class Products extends StatelessWidget {
const Products({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for(var product in context.watch<ProductList>().products)
ListTile(
leading: Text(product.id),
title: Text(product.name),
subtitle: Text(product.ingredients.join(', ')),
),
]
);
}
}
您可以在Dart Pad. Hope this helps. Please refer to How to create a Minimal, Reproducible Example上查看。
抱歉,这根本不是提供商的问题
发生的事情是,当我将产品分配给产品列表时,成分列表是一个参考,在使用后被控制器清除,所以在代码中是这样的:
List<String> ingredients = [];
void onAddIngredient(){
ingredients.add(ingredientController.text);
}
void onSubmit(){
final myNewProduct = Product(
name: nameController.text,
id: idController.text,
ingredients:ingredients
)
providerAction(myNewProduct); // This is where it gets added to _products
nameController.clear();
idController.clear();
ingredientController.clear();
ingredients.clear(); // This was the problem where I was deleting the reference
}