问题描述
我正在使用 Hive 来存储与 Card
相关的 Extension
项的整个列表。在所选扩展程序的屏幕中,我正在显示此扩展程序的卡片,并带有一堆过滤器/排序。
为此,我使用 ValueListenableBuilder
获取当前扩展名及其卡片。
当我过滤/排序这个列表时,我想将它们存储到我的 Provider
类中,因为我想在另一个屏幕中重复使用这个列表。
但我们执行 context.read<ShowingCardsProvider>().setAll(sortedList)
,我收到此错误:
setState() or markNeedsBuild() called during build.
我暂时不听ShowingCardsProvider
。
你能向我解释一下这里有什么问题吗?
谢谢!
main.dart
runApp(MultiProvider(
providers: [
ChangeNotifierProvider.value(value: AuthProvider()),ChangeNotifierProvider.value(value: UserProvider()),ChangeNotifierProvider.value(value: ShowingCardsProvider()),],child: MyApp(),));
showing_cards_provider.dart
import 'dart:collection';
import 'package:Flutter/material.dart';
import 'package:pokecollect/card/models/card.dart';
class CardsProvider extends ChangeNotifier {
final List<CardModel> _items = [];
UnmodifiableListView<CardModel> get items => UnmodifiableListView(_items);
void setAll(List<CardModel>? items) {
_items.clear();
if (items != null || items!.isNotEmpty) {
_items.addAll(items);
}
notifyListeners();
}
void addAll(List<CardModel> items) {
_items.addAll(items);
notifyListeners();
}
void removeAll() {
_items.clear();
notifyListeners();
}
}
extension_page.dart
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,body: SafeArea(
child: LayoutBuilder(builder: (context,constraints) {
return CustomScrollView(
slivers: [
SliverAppBar(
...
),...
SliverPadding(
padding: EdgeInsets.symmetric(horizontal: 16.0),sliver: ValueListenableBuilder(
valueListenable: ExtensionBox.Box.listenable(keys: [_extensionUuid]),builder: (ctx,Box<Extension> Box,child) {
List<CardModel>? cardsList = Box
.get(_uuid)!
.cards
?.where((card) => _isCardPassFilters(card))
.cast<CardModel>()
.toList();
var sortedList = _simpleSortCards(cardsList);
context.read<ShowingCardsProvider>().setAll(sortedList);
return _buildCardListGrid(sortedList);
},),]
);
}),);
}
解决方法
这确实是因为我正在使用 ValueListenableBuilder
,并且在构建 Widget 时,notifyListeners
被调用(到我的提供程序中)。
我的修补程序是这样做的:
return Future.delayed(
Duration(milliseconds: 1),() => context.read<ShowingCardsProvider>().setAll(list),);
不是很漂亮,但是很管用?
如果你有更优雅的方式,欢迎评论!