StreamBuilder,等待一个流在未来发出


return ref.watch(findStoreProvider).when(
data: (store) {
_store = store;
return _map;
},
error: (error, stackTrace) => Text(error.toString()),
loading: () => VpLoadingPage(text: 'Loading Google map'));
}

我需要上面的代码保持在加载状态,直到store.map$有一个发射(这发生在提供者类底部的findVgnItms())。所以它本质上是一个StreamBuilder,等待一个流在未来发出。怎么做呢?我期待这:ref.watch(findStoreProvider)被转换成一个流,并与store.$map结合,但这是在未来,所以似乎不可能?:

return ref.watch(findStoreProvider).when(
data: (store) {
_store = store;
return _map;
},
error: (error, stackTrace) => Text(error.toString()),
loading: () => VpLoadingPage(text: 'Loading Google map'));
}
@override
Widget build(BuildContext context, WidgetRef ref) {
if (defaultTargetPlatform == TargetPlatform.android) {
AndroidGoogleMapsFlutter.useAndroidViewSurface = true;
}
_vm = ref.watch(findPageVm);
_widgetRef = ref;
return ref.watch(findStoreProvider).when(
data: (store) {
_store = store;
return _map;
},
error: (error, stackTrace) => Text(error.toString()),
loading: () => VpLoadingPage(text: 'Loading Google map'));
}
Widget get _map {
return StreamBuilder(
stream: _store.map$,
builder: (context, AsyncSnapshot<VpMap> snapshot) {
return _googleMap(map: snapshot.data);
});
}
Widget _googleMap({VpMap? map}) {
final x = _widgetRef.watch(provider1);
return Stack(children: [
VpLoadingPage(text: 'Loading Google map'),
AnimatedOpacity(
curve: Curves.fastOutSlowIn,
opacity: x ? 1.0 : 0,
duration: const Duration(milliseconds: 600),
child: GoogleMap(
markers: map?.markers ?? const <Marker>{},
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(
_store.userPosition.latitude, _store.userPosition.longitude),
zoom: map?.zoom ?? 13,
),
onMapCreated: (GoogleMapController controller) {
_vm.controller.complete(controller);
Future.delayed(const Duration(milliseconds: 550),
() => _widgetRef.read(provider1.notifier).isLoaded());
},
)),
]);
}

拥有带有流的未来提供者的类:

final findStoreProvider = FutureProvider((provider) async {
final userStore = await provider.watch(userStoreProvider.future);
return FindStore(provider, userStore: userStore);
});
class FindStore extends Store {
FindStore(this.$provider, {required UserStore userStore}) {
map$ ??= _mapController.stream;
findVgnItms();
_userStore = userStore;
}
final Ref $provider;
Stream<VpMap>? map$;
late final StreamController<VpMap> _mapController =
StreamController.broadcast();
late UserStore _userStore;
Set<Marker> markers = <Marker>{};
Stream<String?>? searchTerm;
Position get userPosition => _userStore.userPosition;
Future<List<VgnItmEst>> _$search(String searchTerm) async {
final result =
await $provider.watch(searchResultsProvider(searchTerm).future);
return result;
}
Set<Marker> _mapSearchResultsToMarkers(List<VgnItmEst> searchResults) {
return searchResults
.map((searchResult) => Marker(
markerId: MarkerId(searchResult.id.toString()),
position: LatLng(searchResult.establishment!.location!.lat,
searchResult.establishment!.location!.lng)))
.toSet();
}
Future<FindStore> findVgnItms([String searchTerm = '']) async {
markers = _mapSearchResultsToMarkers(await _$search(searchTerm));
final map = VpMap(position: _userStore.userPosition, markers: markers);
_mapController.add(map);
return this;
}
}

如果需要等待Future完成的Stream,您可能需要查看异步生成器async*yield*关键字

下面是一个简短的例子:

Stream<MyObject> getStreamThatWaitsOnFuture() async* {
await functionThatReturnsAFuture();
yield* functionThatReturnsAStream();
}

我在这里写了一篇关于它的短文:https://medium.com/@dumazy/create-astream-that-requires-future-indart-692f6f089a7e

最新更新