Consumers
Consumer — это виджет, который служит связующим звеном между Widget tree и Provider tree.
Единственное существенное отличие Consumer от обычных виджетов заключается в том, что Consumer получает доступ к Ref. Это позволяет ему читать providers и отслеживать их изменения. Подробнее см. Refs.
Consumers представлены в нескольких вариантах, в основном для удобства и личных предпочтений разработчика. Вы можете встретить:
- Consumer, "builder" виджет (аналогичный FutureBuilder).
Он позволяет виджетам взаимодействовать с providers, не наследуясь ни от чего, кроме
StatelessWidgetилиStatefulWidget.// Наследуемся от StatelessWidget как обычно
class MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
// Виджет, похожий на FutureBuilder
return Consumer(
// Колбэк "builder" предоставляет параметр "ref"
builder: (context, ref, _) {
// Через ref можно подписываться на providers
final value = ref.watch(myProvider);
return Text(value.toString());
},
);
}
} - ConsumerWidget, разновидность
StatelessWidget. Вместо наследования отStatelessWidget, вы наследуетесь отConsumerWidget. Он ведёт себя так же, за исключением того, что методbuildполучает дополнительный параметр WidgetRef.// Наследуемся от ConsumerWidget вместо StatelessWidget
class MyWidget extends ConsumerWidget {
// "build" получает дополнительный параметр
Widget build(BuildContext context, WidgetRef ref) {
// Через "ref" можно подписываться на providers
final value = ref.watch(myProvider);
return Text(value.toString());
}
} - ConsumerStatefulWidget, разновидность
StatefulWidget.
Как и в предыдущем случае, вместо наследования отStatefulWidgetвы наследуетесь отConsumerStatefulWidget. А вместоStateвы наследуетесь от ConsumerState. Главное отличие заключается в том, что ConsumerState предоставляет свойствоref.В качестве альтернативы, вы можете найти дополнительные consumers в пакете hooks_riverpod. Они объединяют consumers Riverpod с flutter_hooks. Если вас не интересуют хуки, вы можете их игнорировать.// Наследуемся от ConsumerStatefulWidget вместо StatefulWidget
class MyWidget extends ConsumerStatefulWidget {
ConsumerState<MyWidget> createState() => _MyWidgetState();
}
// Наследуемся от ConsumerState вместо State
class _MyWidgetState extends ConsumerState<MyWidget> {
// Доступно свойство "ref"
Widget build(BuildContext context) {
// Через "ref" можно подписываться на providers
final value = ref.watch(myProvider);
return Text(value.toString());
}
}
Какой вариант использовать?
Выбор consumer в основном зависит от личных предпочтений.
Можно использовать Consumer для всего — это более универсальный, но чуть более многословный вариант.
Но это разумная цена, если вам не нравится, как Riverpod использует StatelessWidget и StatefulWidget.
Но если у вас нет твердого мнения, мы рекомендуем использовать ConsumerWidget (или ConsumerStatefulWidget если вам нужен State).
Почему мы не можем использовать StatelessWidget + context.watch?
В альтернативных пакетах, таких как provider, можно использовать context.watch чтобы подписываться на providers.
Это работает внутри любого виджета, если у вас есть BuildContext. Так почему же в Riverpod это не так?
Причина в том, что полагаться только на BuildContext вместо Ref не позволило бы надёжно реализовать механизм Automatic disposal.
Существуют способы сделать реализацию, которая «в большинстве случаев работает» с BuildContext,
но проблема в том, что есть множество тонких edge-case’ов, которые могут незаметно ломать auto-dispose.
Это привело бы к утечкам памяти, но это не главная проблема. Automatic disposal ресурсов важнее тем, что оно останавливает выполнение ненужного кода. Если auto-dispose не сработает, provider может продолжать, например, выполнять сетевые запросы в фоне. Поэтому Riverpod предпочёл не жертвовать надёжностью ради небольшого удобства.
Чтобы смягчить неудобства, связанные с использованием ConsumerWidget/ConsumerStatefulWidget вместо StatelessWidget/StatefulWidget,
Riverpod предоставляет различные рефакторинги в IDE, таких как VS Code и Android Studio.

Чтобы включить их в вашей IDE, см. раздел Getting started