List.add 和手动添加项目到 Riverpod StateNotifier<List<String>> 之间的区别

Gio*_*gio 3 state dart flutter riverpod

我想学习如何使用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),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

问题

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?预先非常感谢您。

Ran*_*rtz 7

国家必须以一种oldValue == newValue错误的方式改变。默认情况下,向列表中添加元素会.add改变列表的位置,因此保留了相等性。这就是为什么所有的例子都有类似的东西state = [...state, foo],这样一个全新的列表就处于状态,并且它不等于旧列表。