Flutter - 提供程序不更新数据
我正在使用Provider来确保小部件之间的数据一致性。我刚刚了解到,在访问小部件中的数据时,声明的 Provider 对象的级别很重要。因此,我在顶部创建了一个 Provider 变量,并尝试将其作为参数传递给children、stateless &和children。有状态的小部件。
在有状态小部件中,用户选择产品的尺寸。在无状态小部件中,用户点击按钮将具有所选规格的所选项目添加到购物车。之后,API 会处理所有内容,但到那时,当用户选择其他大小时,Provider 不会更新其保存的初始数据。它总是停留在初始数据上,或者在我的例子中是产品的初始尺寸。
这是我的:顶级父小部件:
@override
Widget build(BuildContext context) {
// initialize
var provider = Provider.of<ProductDetailProvider>(context, listen: true);
provider.detailModel = widget.detailModel!;
provider.seciliBeden = int.parse(widget.detailModel!.Stoks.first.Beden);
provider.stokId = -1;
return Scaffold(
backgroundColor: AppTheme.containerColor,
body: SafeArea(
bottom: false,
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Stack(
children: [
ImageViewBuilder(
pageController: imagePageController,
productDetailModel: widget.detailModel,
resims: resims,
),
DraggableScrollableSheet(
initialChildSize: 0.3,
maxChildSize: 1,
minChildSize: 0.3,
builder: (context, controller) {
return DraggableProductView(
scrollController: controller,
detailModel: widget.detailModel,
provider: provider, // StatefulWidget
);
},
),
Positioned(
child: Align(
alignment: Alignment.bottomCenter,
child: AddToCartBottomBar(
productDetailModel: widget.detailModel!,
productDetailProvider: provider, //StatelessWidget
),
),
),
],
),
),
),
);
}
StatefulWidget:这就是我在 DraggableProductView 中更改 Provider 对象的方式:
onTap: () {
setState(() {
seciliBeden =
widget.detailModel!.Stoks[index].Beden;
});
widget.provider!
.changeSeciliBeden(int.parse(seciliBeden));
},
在这个 StatefulWidget 中,我可以使用更新的数据打印更新的提供程序。 ChangeSeciliBeden 还会触发提供程序内部的 ChangeStockId 函数。
StatelessWidget:AddToCartBottom 小部件包含多个无状态小部件。这是 AddToCartButton 的 onTap 方法:
onTap: () async {
// This line prints only initial size & stock id of the product.
// It does not print updated data
print("yukarı: ${productDetailProvider!.stokId}");
// ...
// ...
// ...
},
最后,这是我的提供程序类:
class ProductDetailProvider extends ChangeNotifier {
late ProductDetailModel detailModel;
late int seciliBeden;
late int stokId;
// This method works too. It prints updated data.
changeSeciliBeden(int value) {
seciliBeden = value;
prepareStokId();
print("provider secili beden: $seciliBeden");
print("provider stok id: $stokId");
notifyListeners();
}
changeStokId(int value) {
stokId = value;
notifyListeners();
}
// This method works. I checked that. If block is true always once.
prepareStokId() {
detailModel.Stoks.forEach((element) {
if (element.Beden == seciliBeden.toString()) {
changeStokId(element.StokId);
}
});
notifyListeners();
}
}
有人可以帮助我找出我做错的地方吗?这不是在小部件之间传递数据而不使用参数的方法吗?
I am using Provider to ensure data consistency between widgets. I just learned that the level of declared Provider object is important when accessing data in widgets. So I created one Provider variable at the top and tried to pass it as an argument to children, stateless & stateful widgets.
In a stateful widget, user selects size for a product. In a stateless widget, user taps button to add the selected item with selected specification to cart. Afterwards, API handles all stuff but to that point, when user selects other sizes, Provider does not update the initial data it holds. It always stuck with initial data or in my case initial size of a product.
Here is my: top parent widget:
@override
Widget build(BuildContext context) {
// initialize
var provider = Provider.of<ProductDetailProvider>(context, listen: true);
provider.detailModel = widget.detailModel!;
provider.seciliBeden = int.parse(widget.detailModel!.Stoks.first.Beden);
provider.stokId = -1;
return Scaffold(
backgroundColor: AppTheme.containerColor,
body: SafeArea(
bottom: false,
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Stack(
children: [
ImageViewBuilder(
pageController: imagePageController,
productDetailModel: widget.detailModel,
resims: resims,
),
DraggableScrollableSheet(
initialChildSize: 0.3,
maxChildSize: 1,
minChildSize: 0.3,
builder: (context, controller) {
return DraggableProductView(
scrollController: controller,
detailModel: widget.detailModel,
provider: provider, // StatefulWidget
);
},
),
Positioned(
child: Align(
alignment: Alignment.bottomCenter,
child: AddToCartBottomBar(
productDetailModel: widget.detailModel!,
productDetailProvider: provider, //StatelessWidget
),
),
),
],
),
),
),
);
}
StatefulWidget: this is how I change Provider object in DraggableProductView:
onTap: () {
setState(() {
seciliBeden =
widget.detailModel!.Stoks[index].Beden;
});
widget.provider!
.changeSeciliBeden(int.parse(seciliBeden));
},
Inside this StatefulWidget, I can print updated provider with updated datas. ChangeSeciliBeden also triggers ChangeStockId function inside provider.
StatelessWidget: AddToCartBottom widget holds several stateless widgets. This is the onTap method from AddToCartButton:
onTap: () async {
// This line prints only initial size & stock id of the product.
// It does not print updated data
print("yukarı: ${productDetailProvider!.stokId}");
// ...
// ...
// ...
},
Finally, this is my provider class:
class ProductDetailProvider extends ChangeNotifier {
late ProductDetailModel detailModel;
late int seciliBeden;
late int stokId;
// This method works too. It prints updated data.
changeSeciliBeden(int value) {
seciliBeden = value;
prepareStokId();
print("provider secili beden: $seciliBeden");
print("provider stok id: $stokId");
notifyListeners();
}
changeStokId(int value) {
stokId = value;
notifyListeners();
}
// This method works. I checked that. If block is true always once.
prepareStokId() {
detailModel.Stoks.forEach((element) {
if (element.Beden == seciliBeden.toString()) {
changeStokId(element.StokId);
}
});
notifyListeners();
}
}
Can somebody help me to figure out where I did wrong? Isn't this the way to pass data between widgets without using arguments?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论