К содержимому

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>[];

// 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, мы можем использовать его для взаимодействия со списком задач:


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),
),
],
);
}
}