ChangeNotifierProvider
ChangeNotifierProvider
(есть только в flutter_riverpod/hooks_riverpod) - это
провайдер, который можно прослушивать, а также он хранит в себе ChangeNotifier
из Flutter.
Использование ChangeNotifierProvider
не поощряется Riverpod. Но все же этот провайдер
нужен для:
- простого перехода с
package:provider
и егоChangeNotifierProvider
- поддержки изменяемых состояний, хотя неизменяемые - предпочтительней
Рекомендуется использовать StateNotifierProvider.
Используйте ChangeNotifierProvider
только, когда вы абсолютно уверены,
что вам нужно изменяемое состояние.
Использование изменяемого состояние вместо неизменяемого иногда может быть более
эффективно. Минус заключается в том, что с изменяемым состоянием бывает сложнее
поддерживать приложение, а также это может поломать некоторый функционал.
Например использование provider.select
для оптимизации перестроек виджетов
может не сработать, если ваше состояние изменяемо, т. к. select
не заметит
изменения состояния.
Использование неизменяемых структур данных иногда работает быстрее.
Поэтому важно делать бенчмарки конкретно вашего случая, чтобы убедиться,
действительно ли вы повышаете производительность, используя ChangeNotifierProvider
.
В качестве примера мы можем использовать ChangeNotifierProvider
для реализации
списка задач.
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>[];
// Добавление задач
void addTodo(Todo todo) {
todos.add(todo);
notifyListeners();
}
// Удаление задач
void removeTodo(String todoId) {
todos.remove(todos.firstWhere((element) => element.id == todoId));
notifyListeners();
}
// Задача выполнена/не выполнена
void toggle(String todoId) {
for (final todo in todos) {
if (todo.id == todoId) {
todo.completed = !todo.completed;
notifyListeners();
}
}
}
}
// Используем ChangeNotifierProvider для взаимодействия с TodosNotifier
final todosProvider = ChangeNotifierProvider<TodosNotifier>((ref) {
return TodosNotifier();
});
Теперь, когда мы объявили ChangeNotifierProvider
, мы можем использовать его
для взаимодействия со списком задач:
class TodoListView extends ConsumerWidget {
const TodoListView({super.key});
Widget build(BuildContext context, WidgetRef ref) {
// перестройка виджета, когда список задач изменился
List<Todo> todos = ref.watch(todosProvider).todos;
// Отображение задач в прокручиваемом списке
return ListView(
children: [
for (final todo in todos)
CheckboxListTile(
value: todo.completed,
// По клику меняем статус задачи
// выполнена/не выполнена
onChanged: (value) =>
ref.read(todosProvider.notifier).toggle(todo.id),
title: Text(todo.description),
),
],
);
}
}