[英]How to change the stream in StreamProvider in Flutter
I'm consuming a stream from Firebase Firestore with a StreamProvider
from the provider
-package like the below code snippet shows ( DatabaseService.streamVehicles
is just a wrapper function to the actual query to Firestore).我正在使用来自 Firebase Firestore 的 stream 和来自
provider
的StreamProvider
- 包,如下面的代码片段所示( DatabaseService.streamVehicles
只是 ZC1C425268E68785D1AB5074FC 的包装器)
In response to user events, the locationId
variable will be set to different ids to filter in the Firestore query.为响应用户事件,
locationId
变量将设置为不同的 id 以在 Firestore 查询中进行过滤。 However, whenever locationId
changes, the component will rebuild, but the function passed to the create
-parameter will not be called again, so the new value of locationId
will not be passed to the query and the stream is still the same, unfiltered stream. However, whenever
locationId
changes, the component will rebuild, but the function passed to the create
-parameter will not be called again, so the new value of locationId
will not be passed to the query and the stream is still the same, unfiltered stream. How can I make sure a new stream is created whenever locationId
changes?如何确保在
locationId
更改时创建新的 stream?
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;
},
),
);
},
);
}
}
The streamVehicles
method of DatabaseService
is defined as the following. DatabaseService
的streamVehicles
方法定义如下。
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());
}
If you want to create a new stream whenever something happens, and then render the contents of that stream, I'd typically store the stream in the state of the widget: If you want to create a new stream whenever something happens, and then render the contents of that stream, I'd typically store the stream in the state of the widget:
void setLocationId(String newId) {
this.setState(() {
locationId = newId;
});
// TODO: determine the new stream, and set that in the state too
}
Then in your build
method, you use the stream from the state, instead of directly from the service.然后在您的
build
方法中,您使用来自 state 的 stream,而不是直接来自服务。
Use a StreamProvider.family to create a new stream provider unique to each id's.使用 StreamProvider.family 创建一个新的 stream 提供程序,每个 ID 都是唯一的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.