You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Provider未更新ListView:CurrentStoryModel单例是否引发问题?

问题:单例ChangeNotifier更新时组件未刷新

我无法理解为何当CurrentStoryModel.instance发生变化时,ScrollViewStory组件无法更新。怀疑是否是CurrentStoryModel采用单例模式导致的问题?

在代码其他位置调用addSection()后,新章节已成功添加到列表中,但ListView并未更新。

相关组件代码

class Story extends StatelessWidget {
  @override
  Widget build(BuildContext _) {

    return ChangeNotifierProvider<CurrentStoryModel>(
      create: (_) => CurrentStoryModel.instance,
      child: Expanded(
        // fill the whole space
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.blue,
              width: 2,
            ),
          ),
          child: ScrollViewStory(),
        ),
      ),
    );
  }
}


class ScrollViewStory extends StatefulWidget {
  ScrollViewStory({Key? key}) : super(key: key);

  @override
  State<ScrollViewStory> createState() => _ScrollViewStoryState();
}

class _ScrollViewStoryState extends State<ScrollViewStory> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    return Consumer<CurrentStoryModel>(
      builder: (context, currentStoryModel, child) => ListView.builder(
          itemCount: currentStoryModel.sections.length,
          itemBuilder: (BuildContext context, int index) {
            return new StorySection(section: currentStoryModel.sections[index]);
          }),
    );
  }
}

模型代码

class CurrentStoryModel extends ChangeNotifier {

  static final CurrentStoryModel _singleton = CurrentStoryModel._();

  // Singleton accessor
  static CurrentStoryModel get instance => _singleton;

  List<SectionModel> _sections = [];

  CurrentStoryModel._();


  List<SectionModel> get sections => _sections;

  // add new entry
  void addSection(SectionModel newSection) {
    _sections.add(newSection);
    notifyListeners();
  }
}

问题原因与解决方案

核心问题

你在ChangeNotifierProvider中使用create方法返回单例实例是错误用法。create的设计目的是创建新实例,而单例是已存在的对象,用create会导致Provider无法正确监听单例的notifyListeners()调用——Provider内部会认为实例未发生变化(始终是同一个对象),因此不会触发Consumer的重建。

修复方案

将ChangeNotifierProvider的create参数替换为value参数,直接传入单例实例:

class Story extends StatelessWidget {
  @override
  Widget build(BuildContext _) {
    return ChangeNotifierProvider.value(
      value: CurrentStoryModel.instance,
      child: Expanded(
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.blue,
              width: 2,
            ),
          ),
          child: ScrollViewStory(),
        ),
      ),
    );
  }
}

额外验证点

  • 确认调用addSection()的地方确实使用CurrentStoryModel.instance单例(你的单例构造函数是私有,这一点已满足);
  • 若SectionModel是自定义类,无需额外处理不可变性——你是直接向列表添加元素并调用notifyListeners(),修复Provider用法后Consumer即可感知变化。

内容的提问来源于stack exchange,提问作者Carson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 14:40:23