Как изменить поток в StreamProvider во Flutter - PullRequest
0 голосов
/ 11 апреля 2020

Я использую поток из Firebase Firestore с StreamProvider из пакета provider, как показано в следующем фрагменте кода (DatabaseService.streamVehicles - это просто функция-обертка для фактического запроса к Firestore).

В ответ на пользовательские события переменная locationId будет иметь разные идентификаторы для фильтрации в запросе Firestore. Однако всякий раз, когда locationId изменяется, компонент перестраивается, но функция, переданная параметру create, больше не будет вызываться, поэтому новое значение locationId не будет передано в запрос, и поток все еще будет тот же нефильтрованный поток. Как я могу убедиться, что новый поток создается при каждом изменении locationId? 1011 *

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 для DatabaseService определяется следующим образом.

  static Stream<List<Vehicle>> streamVehicles(
    String organizationId, {
    String locationId,
  }) {
    final Query ref = _firestore
        .collection('organizations')
        .document(organizationId)
        .collection('vehicles')
        .where(
          "location.id",
          isEqualTo: locationId,
        );

    return ref.snapshots().map((vehicleSnapshots) => vehicleSnapshots.documents
        .map((vehicleSnapshot) => Vehicle.fromFirestore(vehicleSnapshot))
        .toList());
  }

1 Ответ

0 голосов
/ 11 апреля 2020

Если вы хотите создать новый поток всякий раз, когда что-то происходит, а затем визуализировать содержимое этого потока, я обычно храню поток в состоянии виджета:

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

Затем в вашем build метод, вы используете поток из состояния, а не напрямую из сервиса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...