Flutter:使用Riverpod StateProvider删除列表项后UI无法实时更新
Flutter Riverpod 删除列表项后 UI 无法实时更新的解决方案
问题核心原因
- FutureBuilder 仅单次执行:原代码中
FutureBuilder仅在页面首次构建时调用productRepository.getAll(),删除操作不会触发其重新执行,导致UI无法获取最新数据。 - 状态更新未触发监听:直接修改StateProvider持有的列表实例(
productList.remove(product)),即使调用update,由于列表是同一个引用,Riverpod无法检测到状态变化,不会通知UI刷新。 - UI未绑定状态监听:
productListTile使用的是FutureBuilder返回的本地列表,而非监听StateProvider的状态,状态更新无法同步到UI。
修正后的代码实现
1. 定义StateNotifier管理状态
import 'package:flutter_riverpod/flutter_riverpod.dart'; class ProductListNotifier extends StateNotifier<List<Product>> { ProductListNotifier() : super([]) { // 初始化时加载数据 _loadProducts(); } final ProductRepository productRepository = ProductRepository(); // 从数据库加载产品列表 Future<void> _loadProducts() async { final products = await productRepository.getAll(); // 赋值新列表实例,触发状态更新 state = products; } // 删除产品并更新状态 Future<void> deleteProduct(int productId) async { // 先删除数据库数据 await productRepository.delete(productId); // 创建新列表移除目标产品,触发UI刷新 state = state.where((product) => product.id != productId).toList(); } } // 提供状态给UI使用 final productListProvider = StateNotifierProvider<ProductListNotifier, List<Product>>((ref) { return ProductListNotifier(); });
2. 修改ProductScreen组件
class ProductScreen extends ConsumerWidget with FilteredList { ProductScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final searchText = ref.watch(searchTextProvider); return Scaffold( floatingActionButton: createProductButton(context), appBar: AppBar( title: const Text("Tela de Produtos"), ), body: Column( children: [ searchProductField(ref), const SizedBox(height: 16), productList(context, ref, searchText), ], ), ); } Widget productList(BuildContext context, WidgetRef ref, String searchText) { // 监听产品列表状态,状态变化自动刷新UI final productList = ref.watch(productListProvider); if (productList.isEmpty) { return const Center(child: Text("Nenhum produto encontrado")); } // 处理搜索过滤逻辑 final filteredList = searchText.isEmpty ? productList : productList.where((p) => p.name.toLowerCase().contains(searchText.toLowerCase())).toList(); return productListTile(filteredList, ref); } Widget productListTile(List<Product> productList, WidgetRef ref) { return ListView.builder( itemCount: productList.length, itemBuilder: (context, index) { final product = productList[index]; return Slidable( endActionPane: ActionPane( motion: const ScrollMotion(), children: [ SlidableAction( onPressed: (context) async { // 调用StateNotifier的删除方法 await ref.read(productListProvider.notifier).deleteProduct(product.id!); }, backgroundColor: Colors.red, foregroundColor: Colors.white, icon: Icons.delete, label: "Deletar", ) ], ), child: ListTile( title: Text(product.name), subtitle: Text(product.brand ?? ''), trailing: Text(product.price.toStringAsFixed(2)), ), ); }, ); } }
关键优化点
- 状态管理逻辑封装:用
StateNotifier统一处理数据加载、删除逻辑,避免UI层直接操作状态和数据库,保证代码可维护性。 - 触发状态更新的正确方式:每次更新状态时创建新的列表实例(
state = state.where(...).toList()),让Riverpod能够检测到状态变化,自动通知UI刷新。 - 直接监听状态:移除
FutureBuilder,通过ref.watch(productListProvider)直接绑定状态,状态更新时UI自动重建。
内容的提问来源于stack exchange,提问作者Leonardo Maito
相关产品推荐
相关产品推荐

