如何从 class 访问没有上下文的提供者字段?
How to access to provider field from class that do not have context?
我正在使用 Provider
。我有两个 classes:class TenderApiData {}
它是独立的 class(不是小部件)。如何将 accesstoken
写成 AppState
?
class AppState extends ChangeNotifier // putted to ChangeNotifierProvider
{
String _accesstoken; // need to fill not from widget but from stand alone class
String _customer; // Fill from widget
List<String> _regions; // Fill from widget
List<String> _industry; // Fill from widget
...
}
我需要从独立 classes.read\write accesstoken
的方法。
或者我的应用架构有问题?
Here 是完整的源代码。
您不能也不应该访问小部件树之外的提供程序。
即使您理论上可以使用 globals/singletons 或 get_it
等替代方法,也不要那样做。
相反,您会希望使用小部件在您的提供商和您的模型之间架起桥梁。
这通常是通过 didChangeDependencies
生命周期实现的,如下所示:
class MyState extends State<T> {
MyModel model = MyModel();
@override
void didChangeDependencies() {
super.didChangeDependencies();
model.valueThatComesFromAProvider = Provider.of<MyDependency>(context);
}
}
provider
附带一个 widget 内置小部件,可帮助处理常见场景,即:
ProxyProvider
ChangeNotifierProxyProvider
一个典型的例子是:
ChangeNotifierProxyProvider<TenderApiData, AppState>(
initialBuilder: () => AppState(),
builder: (_, tender, model) => model
..accessToken = tender.accessToken,
child: ...,
);
TL;DR
将 provider
换成 get_it
。后者在全局范围内进行 DI,而不将其范围限定为 BuildContext。 (它实际上有自己的可选范围机制,使用字符串 namedInstance
。)
其余...
我 运行 遇到了类似的问题,我认为这归结为 Provider 强制执行某种类型的(元?)架构,即 Widgets 位于您可能称之为的顶部的架构“机构金字塔”。
换句话说,在这种风格中,小部件了解业务逻辑(因此得名 BLoC 架构),它们 运行 展示,与 [=46 推广的 ViewController
范式不同=] 也可能是 MVVM 设置。
在这种架构风格中,当一个小部件创建一个子小部件时,它也会为该小部件创建模型。此处上下文可能很重要,例如,如果您同时显示同一子部件的多个实例,则每个实例都需要其自己的基础模型实例。在小部件或其后代中,您的 DI 系统需要 Context 才能 select 正确的。请参阅 BuildContext::findAncestorWidgetOfExactType
以获取想法 why/how。
这种架构风格似乎受到普通 Flutter 的鼓励,它的范例是应用程序即小部件(“海龟一路向下”)、非可视小部件、布局即小部件和用于 DI 的 InheritedWidget(我相信提供商使用的)
但是
现代应用程序框架库(例如 redux、mobx)鼓励相反的 元架构:位于金字塔底部的小部件。
这里的小部件是“哑巴”,只是 UI 信号发生器和接收器。业务逻辑封装在“商店”中或通过与商店交互的“操作”。小部件仅对正在更新的商店中的相关字段做出反应,并在用户与其交互时发送操作信号。
你应该使用哪个?
根据我的经验,至少在屏幕空间较小的移动设备上,很少需要在渲染树中将模型限定为 b运行ch。如果它突然变得重要,那么有很多其他方法可以处理它(索引数组、id 查找映射、get_it
中的命名实例),而不是要求将它链接到 UI 渲染的语义。
目前,我在 iOS ViewControllers 上花费了太多时间,我很喜欢执行更好 SoC 的新系统。并且个人发现 Flutter 的一切都是小部件的范式如果不加注意有时会显得有点混乱。但最终这是个人喜好。
你可以使用导航键
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
并将此密钥放入 MaterialApp 并用您的提供商 (TenderApiData) 包装它
ChangeNotifierProvider<TenderApiData>(
create: (_) => TenderApiData(),
child: Consumer<TenderApiData>(builder: (context, tenderApiData , child) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'title',
home: SplashScreen());
}),
);
并使用此导航键从任何地方收听此提供商
navigatorKey.currentContext?.read<TenderApiData>();
我正在使用 Provider
。我有两个 classes:class TenderApiData {}
它是独立的 class(不是小部件)。如何将 accesstoken
写成 AppState
?
class AppState extends ChangeNotifier // putted to ChangeNotifierProvider
{
String _accesstoken; // need to fill not from widget but from stand alone class
String _customer; // Fill from widget
List<String> _regions; // Fill from widget
List<String> _industry; // Fill from widget
...
}
我需要从独立 classes.read\write accesstoken
的方法。
或者我的应用架构有问题?
Here 是完整的源代码。
您不能也不应该访问小部件树之外的提供程序。
即使您理论上可以使用 globals/singletons 或 get_it
等替代方法,也不要那样做。
相反,您会希望使用小部件在您的提供商和您的模型之间架起桥梁。
这通常是通过 didChangeDependencies
生命周期实现的,如下所示:
class MyState extends State<T> {
MyModel model = MyModel();
@override
void didChangeDependencies() {
super.didChangeDependencies();
model.valueThatComesFromAProvider = Provider.of<MyDependency>(context);
}
}
provider
附带一个 widget 内置小部件,可帮助处理常见场景,即:
ProxyProvider
ChangeNotifierProxyProvider
一个典型的例子是:
ChangeNotifierProxyProvider<TenderApiData, AppState>(
initialBuilder: () => AppState(),
builder: (_, tender, model) => model
..accessToken = tender.accessToken,
child: ...,
);
TL;DR
将 provider
换成 get_it
。后者在全局范围内进行 DI,而不将其范围限定为 BuildContext。 (它实际上有自己的可选范围机制,使用字符串 namedInstance
。)
其余...
我 运行 遇到了类似的问题,我认为这归结为 Provider 强制执行某种类型的(元?)架构,即 Widgets 位于您可能称之为的顶部的架构“机构金字塔”。
换句话说,在这种风格中,小部件了解业务逻辑(因此得名 BLoC 架构),它们 运行 展示,与 [=46 推广的 ViewController
范式不同=] 也可能是 MVVM 设置。
在这种架构风格中,当一个小部件创建一个子小部件时,它也会为该小部件创建模型。此处上下文可能很重要,例如,如果您同时显示同一子部件的多个实例,则每个实例都需要其自己的基础模型实例。在小部件或其后代中,您的 DI 系统需要 Context 才能 select 正确的。请参阅 BuildContext::findAncestorWidgetOfExactType
以获取想法 why/how。
这种架构风格似乎受到普通 Flutter 的鼓励,它的范例是应用程序即小部件(“海龟一路向下”)、非可视小部件、布局即小部件和用于 DI 的 InheritedWidget(我相信提供商使用的)
但是
现代应用程序框架库(例如 redux、mobx)鼓励相反的 元架构:位于金字塔底部的小部件。
这里的小部件是“哑巴”,只是 UI 信号发生器和接收器。业务逻辑封装在“商店”中或通过与商店交互的“操作”。小部件仅对正在更新的商店中的相关字段做出反应,并在用户与其交互时发送操作信号。
你应该使用哪个?
根据我的经验,至少在屏幕空间较小的移动设备上,很少需要在渲染树中将模型限定为 b运行ch。如果它突然变得重要,那么有很多其他方法可以处理它(索引数组、id 查找映射、get_it
中的命名实例),而不是要求将它链接到 UI 渲染的语义。
目前,我在 iOS ViewControllers 上花费了太多时间,我很喜欢执行更好 SoC 的新系统。并且个人发现 Flutter 的一切都是小部件的范式如果不加注意有时会显得有点混乱。但最终这是个人喜好。
你可以使用导航键
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
并将此密钥放入 MaterialApp 并用您的提供商 (TenderApiData) 包装它
ChangeNotifierProvider<TenderApiData>(
create: (_) => TenderApiData(),
child: Consumer<TenderApiData>(builder: (context, tenderApiData , child) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'title',
home: SplashScreen());
}),
);
并使用此导航键从任何地方收听此提供商
navigatorKey.currentContext?.read<TenderApiData>();