我在使用“ StreamProvider”和让“ Provider.of”交付商品时遇到问题。我有两个相互关联的问题。 (1)是我无法让ProxyProvider工作(很可能是我误会了它,而这可能不是解决方案)。 (2)小部件Drawer()(或我使用它的方式)似乎阻止了“ Provider.of”。在树上找不到“ StreamProvider”。
在MyApp()中,我最初有:
return MultiProvider(
providers: [
StreamProvider<User>.value(value: AuthService().user),
StreamProvider<UserData>.value(
value: DatabaseServices(uid: 'user.userUid').userData),
StreamProvider<QuerySnapshot>.value(
value: DatabaseServices(uid: 'user.userUid').allTasks),
StreamProvider<List<TaskDetails>>.value(
value: DatabaseServices(uid: 'user.userUid').userTasksByImportance),
StreamProvider<List<PropertyDetails>>.value(
value: DatabaseServices(uid: 'UuO2DO0JUVbVD0R1JqIclI7fprF3')
.userProperties),
],
child: MaterialApp(
theme: themeData,
home: Wrapper(),
routes: {
SettingsForm.id: (context) => SettingsForm(),
TaskList.id: (context) => TaskList(),
AddTask.id: (context) => AddTask(),
EditTask.id: (context) => EditTask(),
PropertyList.id: (context) => PropertyList(),
AddProperty.id: (context) => AddProperty(),
AddUnit.id: (context) => AddUnit(),
TestMarkdown.id: (context) => TestMarkdown(),
},
),
);
我试图使用ProxyProvider将StreamProvider的user.userUid提供给它下面的其他StreamProviders,但是无法正常工作。
接下来在Wrapper()中,我尝试了此操作:
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if (user == null) {
return Authenticate();
} else {
return MultiProvider(
providers: [
StreamProvider<UserData>.value(
value: DatabaseServices(uid: user.userUid).userData),
StreamProvider<List<TaskDetails>>.value(
value: DatabaseServices(uid: user.userUid).userTasksByImportance),
StreamProvider<QuerySnapshot>.value(
value: DatabaseServices(uid: user.userUid).allTasks),
StreamProvider<List<PropertyDetails>>.value(
value: DatabaseServices(uid: user.userUid).userProperties),
],
child: Home(),
);
}
}
}
现在这位于MaterialApp()下面,我认为这不是一个好主意,但是我可以使user.user.Uid对其他StreamProvider可用,并且一切正常。 Home()和HomePage()中的Provider.of(由Home()调用)提供了好东西。
现在Home()有一个抽屉:
return Scaffold(
drawer: buildDrawer(context),
backgroundColor: Colors.blueAccent[50],
appBar: appBar,
body: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
image: DecorationImage(
alignment: Alignment.bottomCenter,
image: AssetImage('assets/property_returns_logo_drawn.png'),
fit: BoxFit.fitWidth),
),
child: HomePage(),
),
);
}
}
Drawer buildDrawer(BuildContext context) {
final user = Provider.of<User>(context);
final userData = Provider.of<UserData>(context);
final userProperties = Provider.of<List<PropertyDetails>>(context);
final double _minHeight = 40;
final double _maxHeight = 40;
return Drawer(
child: ListView(
padding: EdgeInsets.all(0),
children: <Widget>[
DrawerHeader(
和userProperty在抽屉本身内可用,但是从抽屉调用的任何小部件都会产生一个错误,即找不到Provider.of的相关StreamProvider。如果我在MyAPP()中重新命名相关的StreamProvider,则可以找到相关的StreamProvider。但是,除非有我的判断,否则Firestore不会提供任何值,并且对于user.userUid硬编码有效的uid:。显然,这不是解决方案,但可以解决Drawer调用的小部件的问题。
我要寻找的是了解如何使用ProxyProvider,或者如果这不是解决方案,则如何构造我的代码。也许我可以在从Drawer调用的每个小部件中使用StreamProviders(或StreamBuilders),但这感觉不对。代码位于https://github.com/sctajc/property_returns。
答案 0 :(得分:1)
从今天开始,ProxyProvider不能作为StreamProvider起作用,因此您无法按自己的方式使用它。
要回答为什么您的Drawer
可以访问Provider.of<Foo>
却无法访问routes
的原因,是因为MaterialApp
是在您的Drawer
中定义的。>
这是什么意思?这意味着,尽管Wrapper
在Provider.of<Foo>
以下,因此可以访问Wrapper
,但从技术上来说,其他路线是在<{> 1 上方。 / p>
TL:DR
解决方案是像这样在ProxyProvider
中创建一个DatabaseServices
:
ProxyProvider<User, DatabaseServices>(
update: (_, user, __) => DatabaseServices(uid: user?.userUid),
),
然后,如果需要使用UserData,则只需执行以下操作:
Provider.of<DatabaseServices>(context).userData
这样,您可以避免创建同一对象(DatabaseServices)的4个实例,并且可以同时解决问题。但是,您的应用程序逻辑需要进行一些更改才能使其正常运行,我相信这不会有问题。
我希望这可以为您提供帮助,并且您可以继续开发自己的应用!