微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

提供者:在构建过程中调用 setState() 或 markNeedsBuild()

如何解决提供者:在构建过程中调用 setState() 或 markNeedsBuild()

我正在使用 Hive 来存储与 Card 相关的 Extension 项的整个列表。在所选扩展程序的屏幕中,我正在显示此扩展程序的卡片,并带有一堆过滤器/排序。

为此,我使用 ValueListenableBuilder 获取当前扩展名及其卡片。

当我过滤/排序这个列表时,我想将它们存储到我的 Provider 类中,因为我想在另一个屏幕中重复使用这个列表。

但我们执行 context.read<ShowingCardsProvider>().setAll(sortedList),我收到此错误

setState() or markNeedsBuild() called during build.

我暂时不听ShowingCardsProvider

你能向我解释一下这里有什么问题吗?

谢谢!

ma​​in.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),);

不是很漂亮,但是很管用?

如果你有更优雅的方式,欢迎评论!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。