如何在不传递参数的情况下使用 riverpod 系列提供程序
How to use a riverpod family provider without passing parameter
有没有办法在不再次传递参数的情况下访问提供的“.family
”更改通知程序(已经实例化,传递正确的参数)的实例?
在提供商中
当您创建 ChangeNotifier 的提供程序(需要参数)时,您可以获得它提供的相同更改通知程序 Provider.of<ChangeNotif>(context)
;
class ChangeNotif extends ChangeNotifier {
final String id;
const ChangeNotif(this.id);
}
ChangeNotifierProvider(create: (_) => ChangeNotif("dash"));
一旦使用正确的参数创建了提供者,您就可以在该小部件树的任何位置获取它提供的任何内容,而无需使用 Provider.of<ChangeNotif("dash")>(context)
之类的任何语法,而是 Provider.of<ChangeNotif>(context)
.
在里弗波德
因为在获取它的实例时必须将参数传递给提供者,所以我不得不将提供者分配给一个变量,以便将它传递给需要提供者的更改通知程序的子项提供。
final changeNotifProvider = ChangeNotifierProvider.family<ChangeNotif, String>((ref, id) => ChangeNotif(id));
class A extends HookWidget {
build() {
final _changeNotifProvider = changeNotifProvider("dash");
final _changeNotif = useProvider(_changeNotifProvider);
return Column(
children: [
B(),
c(_changeNotifProvider),
]
);
}
}
有没有办法获取实例化的 _changeNotif
而无需将其作为参数传递给子窗口小部件?有什么方法可以在另一个不是 A 的子窗口小部件中获取 _changeNotif 的相同实例(例如在 Provider 中使用 Provider.of<ChangeNotif>(context)
而无需传递新参数)?
查看 riverpod 示例,了解它如何解决该问题 Marvel Example
使用 riverpo 系列与 Provider 包的优势在于,provider 不允许您在小部件树下读取相同 class 的多个实例,而 riverpod 系列没有该限制
在提供商中
MultiProvider(
providers: [
ChangeNotifierProvider<ChangeNotif>(
create: (_) => ChangeNotif('dash')
),
ChangeNotifierProvider<ChangeNotif>(
create: (_) => ChangeNotif('dash2')
),
// and many more of the same provider but different initial value
].
child: MyWidget()
);
然后在 MyWidget
中执行 Provider.of<ChangeNotif>(context)
时你只能得到 MultiProvider 创建的最后一个,无法区分同一类型的多个提供者,现在在 riverpod 中有一个解决方案和一种传递方式在家庭中将使用具有初始值的 ScopedProvider。
final _idProvider = ScopedProvider<String>(null);
class A extends HookWidget {
@override
Widget build() {
final _changeNotif = useProvider(changeNotifProvider("dash"));
return ProviderScope(
overrides: [
_idProvider .overrideWithValue("dash"),
],
child: Column(
children: [
B(),
c(),
]
)
);
}
}
现在所有小部件(B 和 C)都可以读取用于创建家庭的参数,如果提供者已经存在,它将检索它而无需重新创建它
class A extends HookWidget {
@override
Widget build() {
final id = useProvider(_idProvider);
final _changeNotif = useProvider(changeNotifProvider(id)); //the ProviderContainer will check if there is already a family with that id and retrieve it
return Text(_changeNotif.id);
}
}
我使用此扩展来获取 StateNotifierProviderFamily
个实例的所有实例,但您也可以为 ChangeNotifierProviderFamily
执行此操作。您确实需要在提供商中注册它们:
extension StateNotifierProviderFamilyExtension<
Notifier extends StateNotifier<Value>,
Value,
Param> on StateNotifierProviderFamily<Notifier, Value, Param> {
/// Get all the registered versions of this `StateNotifierProviderFamily`
///
/// This function requires a reader to the current `ProviderScope` to
/// get the `familyKeysStorageProvider`
///
/// The family needs to be registered with the `familyKeysStorageProvider`,
/// like this:
///
/// ```dart
/// final keyStorage = ref.read(familyKeysStorageProvider(myProvider));
/// keyStorage.state.add(myKey);
/// ```
Iterable<T> all<T extends StateNotifierProvider<Notifier, Value>>(
Reader read) {
return read(_familyKeysStorageProvider(this))
.state
.map((key) => call(key) as T);
}
Set<dynamic> keys(Reader read) =>
read(_familyKeysStorageProvider(this)).state;
void addKey(Reader read, dynamic key) => this.keys(read).add(key);
}
/// Use this provider to register keys for a `StateNotifierProviderFamily`
/// object.
///
/// After registration of the keys, it is possible to retrieve all registered
/// instances with the `all(Reader read)` method on `StateNotifierProviderFamily`
final _familyKeysStorageProvider =
StateProvider.family<Set<dynamic>, StateNotifierProviderFamily>((ref, key) {
return {};
});
您可以这样报名:
final myStateProvider = StateNotifierProvider.family<
MyStateNotifier,
MyState,
MyKey>(
(ref, key) {
myStateProvider.addKey(ref.read, key);
return MyStateNotifier(ref.read, key);
},
);
当然,您还需要导入扩展程序才能正常工作。
对于 ChangeNotifierProviderFamily
我想应该是这样的(我还没有测试过):
extension ChangeNotifierProviderFamilyExtension<Notifier extends ChangeNotifier,
Param> on ChangeNotifierProviderFamily<Notifier, Param> {
Iterable<T> all<T extends ChangeNotifierProvider<Notifier>>(Reader read) {
return read(_notifierFamilyKeysStorageProvider(this))
.state
.map((key) => call(key) as T);
}
Set<dynamic> keys(Reader read) =>
read(_notifierFamilyKeysStorageProvider(this)).state;
void addKey(Reader read, dynamic key) => this.keys(read).add(key);
}
final _notifierFamilyKeysStorageProvider =
StateProvider.family<Set<dynamic>, ChangeNotifierProviderFamily>(
(ref, key) {
return {};
});
有没有办法在不再次传递参数的情况下访问提供的“.family
”更改通知程序(已经实例化,传递正确的参数)的实例?
在提供商中
当您创建 ChangeNotifier 的提供程序(需要参数)时,您可以获得它提供的相同更改通知程序 Provider.of<ChangeNotif>(context)
;
class ChangeNotif extends ChangeNotifier {
final String id;
const ChangeNotif(this.id);
}
ChangeNotifierProvider(create: (_) => ChangeNotif("dash"));
一旦使用正确的参数创建了提供者,您就可以在该小部件树的任何位置获取它提供的任何内容,而无需使用 Provider.of<ChangeNotif("dash")>(context)
之类的任何语法,而是 Provider.of<ChangeNotif>(context)
.
在里弗波德
因为在获取它的实例时必须将参数传递给提供者,所以我不得不将提供者分配给一个变量,以便将它传递给需要提供者的更改通知程序的子项提供。
final changeNotifProvider = ChangeNotifierProvider.family<ChangeNotif, String>((ref, id) => ChangeNotif(id));
class A extends HookWidget {
build() {
final _changeNotifProvider = changeNotifProvider("dash");
final _changeNotif = useProvider(_changeNotifProvider);
return Column(
children: [
B(),
c(_changeNotifProvider),
]
);
}
}
有没有办法获取实例化的 _changeNotif
而无需将其作为参数传递给子窗口小部件?有什么方法可以在另一个不是 A 的子窗口小部件中获取 _changeNotif 的相同实例(例如在 Provider 中使用 Provider.of<ChangeNotif>(context)
而无需传递新参数)?
查看 riverpod 示例,了解它如何解决该问题 Marvel Example
使用 riverpo 系列与 Provider 包的优势在于,provider 不允许您在小部件树下读取相同 class 的多个实例,而 riverpod 系列没有该限制
在提供商中
MultiProvider(
providers: [
ChangeNotifierProvider<ChangeNotif>(
create: (_) => ChangeNotif('dash')
),
ChangeNotifierProvider<ChangeNotif>(
create: (_) => ChangeNotif('dash2')
),
// and many more of the same provider but different initial value
].
child: MyWidget()
);
然后在 MyWidget
中执行 Provider.of<ChangeNotif>(context)
时你只能得到 MultiProvider 创建的最后一个,无法区分同一类型的多个提供者,现在在 riverpod 中有一个解决方案和一种传递方式在家庭中将使用具有初始值的 ScopedProvider。
final _idProvider = ScopedProvider<String>(null);
class A extends HookWidget {
@override
Widget build() {
final _changeNotif = useProvider(changeNotifProvider("dash"));
return ProviderScope(
overrides: [
_idProvider .overrideWithValue("dash"),
],
child: Column(
children: [
B(),
c(),
]
)
);
}
}
现在所有小部件(B 和 C)都可以读取用于创建家庭的参数,如果提供者已经存在,它将检索它而无需重新创建它
class A extends HookWidget {
@override
Widget build() {
final id = useProvider(_idProvider);
final _changeNotif = useProvider(changeNotifProvider(id)); //the ProviderContainer will check if there is already a family with that id and retrieve it
return Text(_changeNotif.id);
}
}
我使用此扩展来获取 StateNotifierProviderFamily
个实例的所有实例,但您也可以为 ChangeNotifierProviderFamily
执行此操作。您确实需要在提供商中注册它们:
extension StateNotifierProviderFamilyExtension<
Notifier extends StateNotifier<Value>,
Value,
Param> on StateNotifierProviderFamily<Notifier, Value, Param> {
/// Get all the registered versions of this `StateNotifierProviderFamily`
///
/// This function requires a reader to the current `ProviderScope` to
/// get the `familyKeysStorageProvider`
///
/// The family needs to be registered with the `familyKeysStorageProvider`,
/// like this:
///
/// ```dart
/// final keyStorage = ref.read(familyKeysStorageProvider(myProvider));
/// keyStorage.state.add(myKey);
/// ```
Iterable<T> all<T extends StateNotifierProvider<Notifier, Value>>(
Reader read) {
return read(_familyKeysStorageProvider(this))
.state
.map((key) => call(key) as T);
}
Set<dynamic> keys(Reader read) =>
read(_familyKeysStorageProvider(this)).state;
void addKey(Reader read, dynamic key) => this.keys(read).add(key);
}
/// Use this provider to register keys for a `StateNotifierProviderFamily`
/// object.
///
/// After registration of the keys, it is possible to retrieve all registered
/// instances with the `all(Reader read)` method on `StateNotifierProviderFamily`
final _familyKeysStorageProvider =
StateProvider.family<Set<dynamic>, StateNotifierProviderFamily>((ref, key) {
return {};
});
您可以这样报名:
final myStateProvider = StateNotifierProvider.family<
MyStateNotifier,
MyState,
MyKey>(
(ref, key) {
myStateProvider.addKey(ref.read, key);
return MyStateNotifier(ref.read, key);
},
);
当然,您还需要导入扩展程序才能正常工作。
对于 ChangeNotifierProviderFamily
我想应该是这样的(我还没有测试过):
extension ChangeNotifierProviderFamilyExtension<Notifier extends ChangeNotifier,
Param> on ChangeNotifierProviderFamily<Notifier, Param> {
Iterable<T> all<T extends ChangeNotifierProvider<Notifier>>(Reader read) {
return read(_notifierFamilyKeysStorageProvider(this))
.state
.map((key) => call(key) as T);
}
Set<dynamic> keys(Reader read) =>
read(_notifierFamilyKeysStorageProvider(this)).state;
void addKey(Reader read, dynamic key) => this.keys(read).add(key);
}
final _notifierFamilyKeysStorageProvider =
StateProvider.family<Set<dynamic>, ChangeNotifierProviderFamily>(
(ref, key) {
return {};
});