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
相关产品推荐
相关产品推荐

