Принципы дизайна 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(),
);
Scope делает связку зависимостей явной и удобной для тестов.
overrideWithValue работает для каждого экземпляра провайдера, включая экземпляры на базе args.
Поведение autoDispose не меняется при использовании subclass + args.

Следующие шаги

Провайдеры и чтение

Посмотрите конкретные шаблоны для watch/read/listen и AsyncProvider.future.

Открыть провайдеры

Мутации

Реализуйте обновления состояния с помощью mutation tokens, mutate и ref.invoke.

Открыть мутации