List.add 和手动将项目添加到 Riverpod StateNotifier<List<String> 之间的区别<List<String>>
Difference between List.add and manually adding item to a 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),
),
);
}
}
问题
在ItemsList
class的add
方法里面,我认为把语句state = [...state, item]
改成state.add(item)
不会有什么区别。但是,这样做会使应用程序不再响应状态更改:点击按钮不会触发对 UI 的更改,并且我在 UI 中看不到任何新项目,直到我热了-重新加载我的应用程序。
所以要明确一点:将 void add(String item) => state = [...state, item];
更改为 void add(String item) => state.add(item);
会打破应用程序状态和 UI 之间的 link。
为什么手动添加列表解构项与使用 List.add
不同?非常感谢您。
状态必须以 oldValue == newValue
为假的方式改变。默认情况下,将元素添加到带有 .add
的列表会在适当的位置改变列表,因此等式 保留 。这就是为什么所有的例子都有类似 state = [...state, foo]
的原因,所以一个全新的列表处于状态,并且不等于旧列表。
我想学习如何使用 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),
),
);
}
}
问题
在ItemsList
class的add
方法里面,我认为把语句state = [...state, item]
改成state.add(item)
不会有什么区别。但是,这样做会使应用程序不再响应状态更改:点击按钮不会触发对 UI 的更改,并且我在 UI 中看不到任何新项目,直到我热了-重新加载我的应用程序。
所以要明确一点:将 void add(String item) => state = [...state, item];
更改为 void add(String item) => state.add(item);
会打破应用程序状态和 UI 之间的 link。
为什么手动添加列表解构项与使用 List.add
不同?非常感谢您。
状态必须以 oldValue == newValue
为假的方式改变。默认情况下,将元素添加到带有 .add
的列表会在适当的位置改变列表,因此等式 保留 。这就是为什么所有的例子都有类似 state = [...state, foo]
的原因,所以一个全新的列表处于状态,并且不等于旧列表。