Flutter:如何使用StreamProvider,FireStore和抽屉进行处理

问题描述 投票:0回答:1

我在使用'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提供给它下面的其他StreamProvider,但无法正常工作。

接下来在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。但是,除非我不加思索并且为user.userUid硬编码有效的uid :,否则Firestore中没有值。显然,这不是解决方案,但可以解决Drawer调用的小部件的问题。

我正在寻找的是了解如何使用ProxyProvider,或者如果这不是解决方案,那么如何构造我的代码。也许我可以在从Drawer调用的每个小部件中使用StreamProviders(或StreamBuilders),但这感觉不对。代码位于https://github.com/sctajc/property_returns

flutter google-cloud-firestore android-contentprovider flutter-provider
1个回答
0
投票

到今天为止,ProxyProvider不能作为StreamProvider起作用,因此您无法按自己的方式使用它。

要回答为什么Drawer可以访问Provider.of<Foo>而没有打开从其打开的路由的原因,是因为routes是在MaterialApp中定义的。

这是什么意思?这意味着Drawer低于Wrapper,因此可以访问Provider.of<Foo>,而其他路线从技术上来说[[上方 Wrapper小部件。

TL:DR

但是,解决方案是像这样在ProxyProvider中创建一个DatabaseServices

ProxyProvider<User, DatabaseServices>( update: (_, user, __) => DatabaseServices(uid: user?.userUid), ),

然后,如果需要利用UserData,则只需执行以下操作:

Provider.of<DatabaseServices>(context).userData

这样可以避免创建同一对象(DatabaseServices)的4个实例,并且可以同时解决问题。但是,您的应用程序逻辑需要进行一些更改才能使其正常运行,我相信这不会有问题。

我希望这可以为您提供帮助,并且您可以继续开发您的应用程序!

© www.soinside.com 2019 - 2024. All rights reserved.