ChangeNotifierProvider
ChangeNotifierProvider
(来自 flutter_riverpod/hooks_riverpod)
是一个用于监听和暴露Flutter本身的 ChangeNotifier 的provider。
Riverpod不鼓励使用 ChangeNotifierProvider
,它的存在主要是为了:
- an easy transition from
package:provider
when using itsChangeNotifierProvider
- 当使用它的
ChangeNotifierProvider
时,简单地从package:provider
迁移。 - 支持可变状态,即使不可变的状态更好。
信息
更倾向于使用 StateNotifierProvider。
只有在绝对需要可变状态时才考虑使用 ChangeNotifierProvider
。
使用可变状态而不是不可变状态有时会更高效。
但缺点是它可能更难维护,并可能破坏各种功能。
比如说如果状态是可变的,
用于优化widget重新构建的 provider.select
可能不起作用,
因为Select会认为值没有改变。
因此,使用不可变的数据结构有时会更快。
制定特定用例的基准测试非常重要,以确保通过使用 ChangeNotifierProvider
时能真正获得性能。
下面是用法示例,我们可以使用 ChangeNotifierProvider
来实现待办清单。
这样做将允许我们公开 addTodo
等方法,让UI修改用户交互中的待办清单:
class Todo {
Todo({
required this.id,
required this.description,
required this.completed,
});
String id;
String description;
bool completed;
}
class TodosNotifier extends ChangeNotifier {
final todos = <Todo>[];
// Let's allow the UI to add todos.
void addTodo(Todo todo) {
todos.add(todo);
notifyListeners();
}
// Let's allow removing todos
void removeTodo(String todoId) {
todos.remove(todos.firstWhere((element) => element.id == todoId));
notifyListeners();
}
// Let's mark a todo as completed
void toggle(String todoId) {
final todo = todos.firstWhere((todo) => todo.id == todoId);
todo.completed = !todo.completed;
notifyListeners();
}
}
// Finally, we are using ChangeNotifierProvider to allow the UI to interact with
// our TodosNotifier class.
final todosProvider = ChangeNotifierProvider<TodosNotifier>((ref) {
return TodosNotifier();
});
现在我们已经定义了一个 ChangeNotifierProvider
,
我们可以用它来与UI中的待办清单交互:
class TodoListView extends ConsumerWidget {
const TodoListView({super.key});
Widget build(BuildContext context, WidgetRef ref) {
// rebuild the widget when the todo list changes
List<Todo> todos = ref.watch(todosProvider).todos;
// Let's render the todos in a scrollable list view
return ListView(
children: [
for (final todo in todos)
CheckboxListTile(
value: todo.completed,
// When tapping on the todo, change its completed status
onChanged: (value) =>
ref.read(todosProvider.notifier).toggle(todo.id),
title: Text(todo.description),
),
],
);
}
}