Vas*_*014 5 mvvm dart flutter gridle flutter-provider
我正在制作一个在线商店,其中在 mvvm 架构上有折扣部分和产品类别,目标是更改添加到购物车的产品数量,除了所有产品的数量发生变化外,一切正常,但所有内容都会显示在数据库中正确,我确信在某个地方我错过了一些重要的东西,我将不胜感激的答案,我将在下面附上屏幕截图
\n根页
\nreturn MultiProvider(\n providers: [\n ChangeNotifierProvider(\n create: (context) => MainPageListViewModel(),\n ),\n ChangeNotifierProvider(\n create: (context) => CartViewModel(),\n child: CartPage()\n ),\n ChangeNotifierProvider(\n create: (context) => AllGoodsViewModel(),\n ),\n ],\n child: MaterialApp(\n initialRoute: \'/\',\n routes: {\n \'/ProfilePage\': (context) => ProfilePage(),\n \'/MainPage\': (context) => MainPage(),\n \'/CartPage\': (context) => CartPage(),\n },\n builder: (context, widget) {\n return ScreenUtilInitService(\n builder: (context) => widget!\n );\n },\n title: \'Flutter Demo\',\n theme: ThemeData(\n primarySwatch: Colors.blue,\n ),\n home: present != null ? present : MainPage()\n ),\n);\n
Run Code Online (Sandbox Code Playgroud)\n类别页面
\nclass AllCategoryGoodsPage extends StatefulWidget {\n\nconst AllCategoryGoodsPage({key, required this.category}) : super(key: key);\n\nfinal CategoryData category;\n\n@override\nState<AllCategoryGoodsPage> createState() => _AllCategoryGoodsPageState();\n\n}\n\nclass _AllCategoryGoodsPageState extends State<AllCategoryGoodsPage> {\n\n@override\nvoid initState() {\n super.initState();\n Provider.of<AllGoodsViewModel>(context, listen: false).fetchAllItems(id: widget.category.id);\n}\n\n@override\nWidget build(BuildContext context) {\n\n final model = Provider.of<AllGoodsViewModel>(context);\n\n return MaterialApp(\n home: Scaffold(\n appBar: AppBar(),\n body: Container(\n width: MediaQuery.of(context).size.width,\n height: MediaQuery.of(context).size.height,\n color: Colors.white,\n child: GridView.builder(\n shrinkWrap: true,\n physics: BouncingScrollPhysics(),\n gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(\n crossAxisCount: 2,\n childAspectRatio: 0.76),\n itemCount: model.goods.length,\n itemBuilder: (context, index) {\n return ViewGoods(model: model.goods[index], index: index);\n }),\n ),\n ),\n );\n}\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n查看商品
\nclass _ViewGoodsState extends State<ViewGoods> {\n\n GlobalKey _key = GlobalKey();\n\n @override\n void initState() {\n super.initState();\n WidgetsBinding.instance.addPostFrameCallback((_){\n Provider.of<AllGoodsViewModel>(context, listen: false).setting(widget.model);\n });\n }\n\n @override\n Widget build(BuildContext context) {\n\n final model = Provider.of<AllGoodsViewModel>(context);\n final size = MediaQuery.of(context).size;\n\n Widget inCart(){\n return Container(\n key: _key,\n height: 31,\n child: GestureDetector(\n onPanDown: (details) {\n Goods? item = widget.model;\n RenderBox _cardBox = _key.currentContext!.findRenderObject() as RenderBox;\n final localPosition = details.localPosition;\n final localDx = localPosition.dx;\n if (localDx <= _cardBox.size.width/2) {\n Goods value = cart.firstWhere((element) => element.id == item.id);\n if (item.optState == 0 ? value.orderCount <= 1 : value.orderCount <= value.opt!.count) {\n setState(() {\n context.read<AllGoodsViewModel>().setCountInCart(0);\n final ind = cart.indexWhere((element) => element.id == item.id);\n if (ind != -1) {\n cart[ind].orderCount = 0;\n SQFliteService.cart.delete(cart[ind].id);\n cart.removeAt(ind);\n NotificationCenter().notify("cart");\n }\n });\n } else {\n model.haveItem(item: item, operation: item.optState == 0 ? -1 : (-1 * value.opt!.count));\n }\n } else {\n model.haveItem(item: item, operation: item.optState == 0 ? 1 : item.count);\n }\n\n },\n child: TextButton(\n style: ButtonStyle(\n backgroundColor: MaterialStateProperty.all(Design.appColor),\n padding: MaterialStateProperty.all(EdgeInsets.symmetric(vertical: 8, horizontal: 10)),\n shape: MaterialStateProperty.all(RoundedRectangleBorder(\n borderRadius: BorderRadius.circular(10.0),\n ))\n ),\n onPressed: (){},\n child: Container(\n child: RichText(\n text: TextSpan(\n text: "",\n children:[\n WidgetSpan(\n alignment: PlaceholderAlignment.middle,\n child: Icon(Icons.remove, size: 14, color: Colors.white),\n ),\n TextSpan(\n text: " ${widget.model.optState == 0 ? (widget.model.minPrice ?? widget.model.price) : widget.model.opt!.price} \xe2\x82\xbd ",\n style: TextStyle(\n color: Colors.white,\n fontSize: 14,\n fontWeight: FontWeight.w500,\n fontFamily: "Inter"\n ),\n ),\n WidgetSpan(\n alignment: PlaceholderAlignment.middle,\n child: Icon(Icons.add, size: 14, color: Colors.white),\n )\n ],\n ),\n ),\n ),\n ),\n ),// Your TextButton code goes here.\n );\n }\n\n Widget noInCart(){\n return Container(\n key: _key,\n height: 31,\n child: TextButton(\n style: ButtonStyle(\n backgroundColor: MaterialStateProperty.all(model.orderBg),\n padding: MaterialStateProperty.all(EdgeInsets.symmetric(vertical: 8, horizontal: 10)),\n shape: MaterialStateProperty.all(RoundedRectangleBorder(\n borderRadius: BorderRadius.circular(10.0),\n ))\n ),\n onPressed: (){\n Goods? item = widget.model;\n model.haveItem(item: item, operation: item.optState == 0 ? 1 : item.count);\n },\n child: Container(\n child: RichText(\n text: TextSpan(\n text: "${widget.model.optState == 0 ? widget.model.minPrice == null ? widget.model.price : widget.model.minPrice : widget.model.opt!.price} \xe2\x82\xbd ",\n style: TextStyle(\n color: widget.model.minPrice != null ? Design.grey : Colors.black,\n decoration: widget.model.optState == 0 && widget.model.minPrice != null ? TextDecoration.lineThrough : TextDecoration.none,\n fontSize: 14,\n fontWeight: FontWeight.w500,\n fontFamily: "Inter"\n\n ),\n children:[\n TextSpan(\n text: widget.model.minPrice == null ? "" : " ${widget.model.price} \xe2\x82\xbd",\n style: TextStyle(\n color: Colors.black,\n decoration: TextDecoration.none,\n fontSize: 14,\n fontWeight: FontWeight.w500,\n fontFamily: "Inter"\n ),\n ),\n\n WidgetSpan(\n alignment: PlaceholderAlignment.middle,\n child: Icon(Icons.add, size: 14, color: Colors.black),\n style: TextStyle(\n color: Colors.black,\n decoration: TextDecoration.none,\n ),\n )\n ],\n ),\n ),\n ),\n ),\n );\n }\n\n\n Widget card({required Size size}) {\n return Container(\n color: Colors.white,\n width: (size.width/2.4) - 11,\n margin: EdgeInsets.only(right: (widget.index.isOdd ? 16 : 5) , left: (widget.index.isOdd ? 5 : 16)),\n child: Column(\n children: [\n Stack(\n children: [\n Container(\n height: (size.width/2 - 16),\n width: (size.width/2),\n padding: EdgeInsets.all(1),\n decoration: BoxDecoration(\n image: DecorationImage(\n fit: BoxFit.cover,\n image: NetworkImage(widget.model.images.first)\n ),\n borderRadius: BorderRadius.all(Radius.circular(10.0)),\n border: Border.all(\n width: 1,\n color: Design.lightGrey\n ),\n ),\n ),\n Visibility(\n visible: model.countInCart == 0 ? false : true,\n child: Container(\n height: (size.width/2 - 16),\n width: (size.width/2),\n decoration: BoxDecoration(\n color: Colors.black.withOpacity(0.5),\n borderRadius: BorderRadius.all(Radius.circular(10.0)),\n ),\n child: Visibility(\n visible: true,\n child: Center(\n child: model.orderCountText,\n ),\n ),\n ),\n )\n ]\n ),\n SizedBox(height: 5),\n Align(\n alignment: Alignment.centerLeft,\n child: Container(\n height: 34.h,\n child: Text(widget.model.name,\n maxLines: 2,\n style: TextStyle(\n fontSize: 14.sp,\n fontWeight: FontWeight.w500,\n fontFamily: "Inter",\n ),\n ),\n ),\n ),\n SizedBox(height: 5),\n Align(\n alignment: Alignment.centerLeft,\n child: (context.read<AllGoodsViewModel>().countInCart == 0) ? noInCart() : inCart()\n )\n ],\n ),\n );\n }\n\n return card(size: size);\n }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n和视图模型
\nclass AllGoodsViewModel extends ChangeNotifier {\n\n List<Goods> goods = List.empty(growable: true);\n late DocumentSnapshot documentSnapshot;\n\n Future<void> fetchAllItems({required String id}) async {\n final data = await FirestoreService.shared.fetchItems(id);\n this.goods = [];\n sortGoods(data);\n }\n\n Future<void> paginateAllGoods({required String id}) async {\n var data = await FirestoreService.shared.fetchRequestItems(documentSnapshot: documentSnapshot, id: id);\n sortGoods(data);\n }\n\n Future<void> sortGoods(Tuple? data) async {\n if (data != null) {\n if (data.data.length == 0) {\n return;\n }\n this.documentSnapshot = data.id;\n final items = data.data as List<QueryDocumentSnapshot<Map<String, dynamic>>>;\n this.goods.addAll(items.map((e) => Goods.fromFirestoreTo(e)).toList());\n notifyListeners();\n }\n }\n\n\n var _countInCart = 0;\n int get countInCart => _countInCart;\n\n var _orderBg = Design.lightGrey;\n Color get orderBg => _orderBg;\n\n var _orderColor = Design.paleWhite;\n Color get orderColor => _orderColor;\n\n var _orderStyle;\n TextStyle get orderStyle => _orderStyle;\n\n var _orderCountText = Text("0");\n Text get orderCountText => _orderCountText;\n\n void setting(Goods item) {\n\n final ind = cart.indexWhere((element) => element.id == item.id);\n if (ind != -1) {\n item.optState = cart[ind].isOpt ? 1 : 0;\n // chooseView.configure(item: item, tag: order.tag)\n setReadyData(index: ind);\n } else {\n //chooseView.configure(item: item, tag: 0)\n setCountInCart(0);\n }\n }\n\n // add and remove product\n void haveItem({required Goods item, required int operation}) async {\n final ind = cart.indexWhere((element) => element.id == item.id);\n if (ind == -1) {\n final minCount = item.optState == 0 ? 1 : item.opt!.count;\n if (item.count < minCount) {\n //order.shake();\n } else {\n cart.add(item);\n final ind = cart.length - 1;\n cart.last.isOpt = item.optState == 0 ? false : true;\n cart.last.orderCount = minCount;\n await SQFliteService.cart.addToCart(cart.last);\n // animate();\n NotificationCenter().notify("cart");\n changeCountInCart(operation);\n countText(index: ind, item: cart.last);\n orderText();\n }\n } else {\n final count = cart[ind].orderCount;\n if (count <= item.count) {} else { return; } //order.shake()\n if (operation < 0 || count + operation <= item.count) {} else { return; } //order.shake()\n cart[ind].orderCount += operation;\n SQFliteService.cart.updateItem(cart[ind].id, {"orderCount":cart[ind].orderCount});\n NotificationCenter().notify("cart");\n changeCountInCart(operation);\n countText(index: ind, item: cart[ind]);\n }\n }\n\n\n // when re-displaying a product\n void setReadyData({required int index}) {\n final empty = cart[index].orderCount == 0;\n empty ? defaultOrderText() : orderText();\n if (empty) { return; }\n setCountInCart(cart[index].orderCount);\n countText(item: cart[index]);\n }\n\n //quantity of goods in the basket\n void countText({int? index, required Goods item}) {\n var ind = index;\n if (index == null) {\n ind = cart.indexWhere((element) => element.id == item.id);\n }\n if (ind == -1) { return; }\n if (cart[ind!].orderCount >= item.count){\n final text = Text.rich(\n TextSpan(\n style: TextStyle(\n fontSize: 22,\n fontFamily: "Inter",\n fontWeight: FontWeight.w400,\n color: Colors.white,\n ),\n text: "$_countInCart",\n children: <TextSpan>[\n TextSpan(text: "\\n\xd0\x9d\xd0\xb5\xd1\x82 \xd0\xb2 \xd0\xbd\xd0\xb0\xd0\xbb\xd0\xb8\xd1\x87\xd0\xb8\xd0\xb8", style: TextStyle(\n fontSize: 16,\n fontFamily: "Inter",\n fontWeight: FontWeight.bold,\n color: Colors.white\n )),\n ],\n ),\n textAlign: TextAlign.center,\n );\n changeOrderCountText(text);\n } else {\n final text = Text("$_countInCart",\n style: TextStyle(\n fontSize: 22,\n fontFamily: "Inter",\n fontWeight: FontWeight.w400,\n color: Colors.white\n ),\n );\n changeOrderCountText(text);\n }\n\n }\n\n void changeOrderCountText(Text widget){\n _orderCountText = widget;\n }\n\n void defaultOrderColor(){\n _orderColor = Design.paleWhite;\n _orderStyle = TextStyle(color: Design.dark);\n }\n\n // add button text\n void orderText() {\n _orderColor = Design.paleWhite;\n _orderStyle = TextStyle(color: Colors.white, fontWeight: FontWeight.w500, fontSize: 14);\n if (_orderBg == Design.paleWhite) {\n _orderBg = Design.appColor;\n }\n }\n\n void defaultOrderText() {\n _orderBg = Design.paleWhite;\n _orderColor = Design.dark;\n _orderStyle = TextStyle(color: Colors.white, fontWeight: FontWeight.w700, fontSize: 14);\n }\n\n void setCountInCart(int value){\n _countInCart = value;\n notifyListeners();\n }\n\n void changeCountInCart(int value){\n _countInCart += value;\n notifyListeners();\n }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n整个问题是,当您通过单击按钮进行更改时,所有产品的数量都会发生变化
\n\n小智 2
我认为问题出在 AllGoodsViewModel() 的 ChangeNotifierProvider 上:
ChangeNotifierProvider(
create: (context) => AllGoodsViewModel(),
),
Run Code Online (Sandbox Code Playgroud)
因为你使用它,并且在任何地方用上下文调用它,它都会返回相同的模型,这就是为什么每个产品都显示相同的计数。
我建议您通过将每个小部件包装在产品列表中来使用 ChangeNotifierProvider.value():
ChangeNotifierProvider.value(
value: MyModel(),
child: ...
)
Run Code Online (Sandbox Code Playgroud)
而且您不需要在全球范围内提供您的模型。
归档时间: |
|
查看次数: |
793 次 |
最近记录: |