Принципите на дизайна зад miniriverpod.
Пакетът умишлено стеснява възможностите, за да държи поведението явно: идентичност на провайдера по args, инжектиране чрез Scope и предсказуеми семантики на жизнения цикъл и освобождаването.
Какво се променя спрямо Riverpod
Вместо генерирани family класове и имплицитни notifier канали, miniriverpod предпочита subclass + args + явен invoke.
Идентичност на провайдера
runtimeType + args hash
Алтернатива на family
Създайте подкласа на Provider / AsyncProvider и подайте super.args((...))
DI резервен вариант
Scope<T>.required + overrideWithValue
Защо това е важно
Можете да разсъждавате за равенството и override-ите с обикновени Dart конструктори, което прави дебъгването и тестовете ясни.
Идентичност на провайдера с args
args определя ключа на провайдера, така че еднакви args означават един и същ кеш запис в ProviderContainer.
Правило за идентичност
Практически последици
- Не е необходим отделен family тип.
- Override-ът за отделен аргумент се прави чрез създаване на екземпляри на провайдера.
- Дръжте 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 токени, mutate и ref.invoke.
Отворете мутациите