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