Принципы дизайна miniriverpod.
Пакет намеренно сужает набор возможностей, чтобы поведение оставалось явным: идентичность провайдера по args, внедрение через Scope и предсказуемая семантика удаления.
Что меняется по сравнению с Riverpod
Вместо сгенерированных family-классов и неявных каналов уведомлений miniriverpod предпочитает subclass + args + явный invoke.
Идентичность провайдера
runtimeType + hash args
Альтернатива family
Наследуйте Provider / AsyncProvider и передавайте super.args((...))
DI-запасной вариант
Scope<T>.required + overrideWithValue
Почему это важно
О равенстве и переопределениях можно рассуждать с помощью обычных конструкторов Dart, что упрощает отладку и тесты.
Идентичность провайдера с args
args определяет ключ провайдера, поэтому одинаковые args означают одну и ту же запись кэша внутри ProviderContainer.
Правило идентичности
Практические последствия
- Отдельный тип family не требуется.
- Переопределение для каждого аргумента выполняется через создание экземпляров провайдера.
- Держите args стабильными и неизменяемыми для предсказуемого кэширования.
Пример: провайдер, похожий на family, + запасной Scope
Используйте аргумент конструктора как идентификатор и внедряйте запасной экземпляр через Scope.
class ProductProvider extends AsyncProvider<List<Product>> {
ProductProvider({this.search = ''}) : super.args((search,));
final String search;
static final fallback = Scope<ProductProvider>.required('product.fallback');
@override
FutureOr<List<Product>> build(ref) async {
final api = ref.watch(productsApiProvider);
return api.search(q: search);
}
}
// Внедрить
ProviderScope(
overrides: [
ProductProvider.fallback.overrideWithValue(ProductProvider(search: 'jeans')),
],
child: const App(),
);
Следующие шаги
Провайдеры и чтение
Посмотрите конкретные шаблоны для watch/read/listen и AsyncProvider.future.
Открыть провайдерыМутации
Реализуйте обновления состояния с помощью mutation tokens, mutate и ref.invoke.
Открыть мутации