ChangeNotifierProvider
ChangeNotifierProvider (来自 flutter_riverpod/hooks_riverpod)
是一个用于监听和暴露Flutter本身的 ChangeNotifier 的provider。
Riverpod不鼓励使用 ChangeNotifierProvider ,它的存在主要是为了:
- an easy transition from package:providerwhen 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),
          ),
      ],
    );
  }
}