如何在Flutter的StreamProvider中更改流

时间:2020-04-11 18:10:52

标签: firebase flutter

我正在使用StreamProvider包中的provider来自Firebase Firestore的流,如下面的代码片段所示(DatabaseService.streamVehicles只是实际查询的包装函数Firestore)。

为响应用户事件,locationId变量将设置为不同的ID,以在Firestore查询中进行过滤。但是,无论何时locationId发生更改,组件都将重建,但是传递给create参数的函数将不会再次调用,因此新的locationId值将不会传递给查询与流仍然相同,未经过滤的流。每当locationId更改时,如何确保创建新的流?

class HomePage extends StatefulWidget {
  static final String id = 'home';

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final CupertinoTabController _tabController =
      CupertinoTabController(initialIndex: 0);

  String locationId;

  void setLocationId(String newId) {
    this.setState(() {
      locationId = newId;
    });
  }

  @override
  Widget build(BuildContext context) {
    print("Building homepage");
    return Consumer<User>(
      builder: (context, user, _) {
        return StreamProvider<List<Vehicle>>(
          create: (context) => DatabaseService.streamVehicles(
            user.organization.id,
            locationId: locationId,
          ),
          catchError: (ctx, err) {
            print("Error in stream");
            print(err);
            return [];
          },
          child: CupertinoTabScaffold(
            controller: _tabController,
            tabBar: CupertinoTabBar(
              activeColor: kHighlightColor,
              items: <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                  icon: Icon(CupertinoIcons.collections),
                  title: Text('Vehicles'),
                ),
                BottomNavigationBarItem(
                  icon: Icon(CupertinoIcons.settings),
                  title: Text('Settings'),
                ),
              ],
            ),
            tabBuilder: (BuildContext context, int index) {
              switch (index) {
                case 0:
                  return VehiclesPage(
                      locationId: locationId, setLocationId: setLocationId);
                case 1:
                  return SettingsPage();
              }
              return null;
            },
          ),
        );
      },
    );
  }
}

streamVehicles的{​​{1}}方法定义如下。

DatabaseService

2 个答案:

答案 0 :(得分:0)

如果您想在发生任何事情时创建一个新的流,然后呈现该流的内容,我通常会将流存储在小部件的状态:

void setLocationId(String newId) {
  this.setState(() {
    locationId = newId;
  });
  // TODO: determine the new stream, and set that in the state too
}

然后在您的build方法中,您使用状态中的流,而不是直接使用服务中的流。

答案 1 :(得分:0)

使用StreamProvider.family创建每个ID唯一的新流提供程序。