List.add 和手动添加项目到 Riverpod StateNotifier<List<String>>

问题描述

我想学习如何使用 Riverpod,因此为此,我正在实现一个小应用程序,该应用程序显示一个项目列表和一个按钮,该按钮在点击时将一个虚拟项目添加到列表中。

问题背景

按下以下应用中的按钮按预期工作(添加了一个虚拟项目,更改立即反映在 UI 中):

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';



void main() => runApp(const ProviderScope(child: MyApp()));

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp(home: HomePage());
}



final itemsProvider = StateNotifierProvider((ref) => ItemsList());

class ItemsList extends StateNotifier<List<String>> {
  ItemsList([List<String> items]) : super(items ?? []);

  void add(String item) => state = [...state,item];
}



class HomePage extends ConsumerWidget {
  const HomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context,ScopedReader watch) {
    final items = watch(itemsProvider.state);
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,children: items.map((e) => Text(e)).toList(),),floatingActionButton: FloatingActionButton(
        onPressed: () => context.read(itemsProvider).add('Other item'),tooltip: 'Add item',child: Icon(Icons.add),);
  }
}

问题

add 类的 ItemsList 方法中,我认为将语句 state = [...state,item] 更改为 state.add(item) 不会有任何区别。但是,这样做会使应用不再响应状态更改:点击按钮不会触发 UI 更改,并且在我热重新加载我的应用之前,我在 UI 中看不到任何新项目。

所以要明确一点:将 void add(String item) => state = [...state,item]; 更改为 void add(String item) => state.add(item); 会破坏应用状态和 UI 之间的联系。

为什么手动添加具有列表解构的项目与使用 List.add 不同?预先非常感谢您。

解决方法

状态必须以 oldValue == newValue 为假的方式改变。默认情况下,将元素添加到带有 .add 的列表会改变列表,因此保留相等。这就是为什么所有的例子都有类似 state = [...state,foo] 的东西,所以一个全新的列表处于状态,它不等于旧列表。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...