Flutter商品详情页ListView无限重复滚动问题解决方法
问题描述
为学校项目开发购物APP,参考Flutter的Shrine示例应用使用示例图片,在商品详情页展示商品图片与信息时,出现ListView无限滚动、商品图片和详情重复显示的问题。
错误原因
核心问题出在商品详情页的代码逻辑:
loadedProduct是通过findById获取的单个Product对象,但错误地将ListView.builder的itemCount设为loadedProduct.length——这里的length并非列表长度,而是Product类中意外可访问的属性(比如字符串长度),导致ListView重复创建大量相同的商品卡片。- 详情页只需要展示单个商品信息,完全不需要用
ListView.builder构建列表,属于组件误用。
修复方案
直接移除ListView.builder,用SingleChildScrollView包裹单个商品卡片即可(满足详情内容超出屏幕时的滚动需求),修改后的代码如下:
修改后的商品详情页代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:MyShoppingApp/provider/CartProvider.dart'; import 'package:MyShoppingApp/db/cart_database.dart'; import 'package:MyShoppingApp/model/cart.dart'; import 'model/products_repository.dart'; import '../model/cart.dart'; class ProductDetailsPage extends StatelessWidget { static const routeName = '/user-products'; ProductDetailsPage({Key? key}) : super(key: key); DBHelper dbHelper = DBHelper(); @override Widget build(BuildContext context) { // 获取当前商品ID final productId = ModalRoute.of(context)!.settings.arguments as String; print(productId); // 获取单个商品对象 final loadedProduct = ProductsRepository().findById(productId); final cart = Provider.of<CartProvider>(context); void saveData(int index) { dbHelper .insert( CartItem( id: index, title: loadedProduct.name, price: loadedProduct.price.toDouble(), quantity: ValueNotifier(1), image: loadedProduct.image, ), ) .then((value) { cart.addTotalPrice(loadedProduct.price.toDouble()); cart.addCounter(); print('Product Added to cart'); }).onError((error, stackTrace) { print(error.toString()); }); } return Scaffold( backgroundColor: Colors.orange[50], appBar: AppBar( backgroundColor: Colors.deepOrange[900], title: const Text("Product details "), leading: IconButton( icon: const Icon( Icons.arrow_back_ios_outlined, color: Colors.black, semanticLabel: 'back to home', ), onPressed: () { Navigator.pop(context); }, ), ), // 用SingleChildScrollView实现页面滚动,包裹单个商品卡片 body: SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 8.0), child: Card( child: Column( children: <Widget>[ SizedBox( height: 300, width: double.infinity, child: Image.asset( loadedProduct.image, fit: BoxFit.cover, ), ), const SizedBox(height: 10), Text( '\$${loadedProduct.price}', style: const TextStyle( color: Colors.grey, fontSize: 20, ), ), const SizedBox( height: 10, ), ElevatedButton( style: ElevatedButton.styleFrom( primary: Colors.blueGrey.shade900), onPressed: () { saveData(Random().nextInt(1000)); }, child: const Text('Add to Cart')), Container( padding: const EdgeInsets.symmetric(horizontal: 10), width: double.infinity, child: Text( loadedProduct.description, textAlign: TextAlign.center, softWrap: true, ), ), ], ), ), ), ); } }
额外优化建议
- 避免每次build都创建
ProductsRepository实例,可通过Provider注入或单例模式优化。 saveData方法中用Random().nextInt(1000)生成购物车项ID可能重复,建议改用DateTime.now().millisecondsSinceEpoch生成唯一ID更可靠。
内容的提问来源于stack exchange,提问作者pleasesendhelp
相关产品推荐
相关产品推荐

