我对Flutter / Dart还是很陌生,我正在使用flutter_bloc bloc /存储库模式。我正在努力从bloc方法中的存储库方法中获取值。我的第一种方法(I get null returned value from a method. Flutter)是在存储库方法中侦听Stream<Position>
并返回将在我的bloc方法中保留的LatLng
。我总是得到null。
因此,我的新方法是使用StreamTransformer
将Stream<Position>
转换为Stream<LatLng>
,但由于.transform
似乎不可用,我被困在编写存储库方法中,并且出现了错误The method 'transform' isn't defined for the class 'Function'
。你能看到我做错了吗?一如既往的感谢。
我的两个方法是:
存储库:
StreamSubscription _positionStreamSubsciption;
Stream<LatLng> getLocationStream() {
print('getLocationStream() called');
print('isTracking was : $isTracking');
LatLng location;
Stream<LatLng> locationStream;
LocationOptions locationOptions = LocationOptions(
accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 0);
try {
if (isTracking == true) {
_positionStreamSubsciption.cancel();
} else {
_positionStreamSubsciption = locationManager
.getPositionStream(locationOptions)
.listen((Position position) {
if (position != null) {
location = LatLng(position.latitude, position.longitude);
handleData(Position position, EventSink<LatLng> sink) =>
sink.add(location);
final transformer =
StreamTransformer<Position, LatLng>.fromHandlers(
handleData: handleData);
return _positionStreamSubsciption.onData.transform(transformer); // .transform trows an ERROR
}
print('getLocationStream() location is : $location');
});
}
isTracking = !isTracking;
print('isTracking is : $isTracking');
} catch (error) {
print('startTracking error: $error');
}
}
bloc:
LatLng locationStream;
StreamSubscription _locationStreamSubscription;
Stream<MapState> _mapGetLocationStreamToState(
GetLocationStream event) async* {
print('_mapGetLocationStreamToState event received : $event');
_locationStreamSubscription =
_mapRepository.getLocationStream().listen((LatLng location) {
locationStream = location;
});
更新:
在对代码进行了一点摆弄之后,我发现了错误所在:
在存储库中,我确实设置了一个侦听器,但实际上需要流本身,所以我添加了_positionStream = locationManager.getPositionStream(locationOptions);
。
在StreamTransformer
的handleData
中,我在侦听器中添加了一个位置,而不是从其参数Stream<LatLng> locationStream
中获取该位置。所以我将其更改为Position position
。
在集团中,我还必须收听来自handleData(Position position, EventSink<LatLng> sink) =>
sink.add(LatLng(position.latitude, position.longitude));
的位置信息流。现在,由于不可能直接从侦听器作用域内部产生状态,而从作用域外部产生状态只会产生当前流值,并且此后不会更新,因此我不得不使用事件循环。我向该组添加了_mapRepository.getLocationStream()
事件,该事件从流中传递到该位置。
在blocLocationUpdated
mapEventToStates
LocationStream状态和位置中。
现在,状态正在按预期流动,并带有新的位置值。
唯一要解决的问题(我实际上以为我没有)是,I had to react to that event yielding the
MapScren
不能容纳来自新状态的值,而在[[ C0]。
BlocBuilder
不是掌握它的正确方法吗?
更新后的代码是:
BlocBuilder:
_mapController.move(userLocation, 16);
存储库:
LatLng userLocation = (state as LocationStream).location;
bloc:
bloc: MapBloc(mapRepository: _mapRepository),
builder: (BuildContext context, MapState state) {
LatLng userLocation = (state as LocationStream).location;
return Scaffold(
..
找到了最后一个问题。在Stream<LatLng> getLocationStream() {
print('getLocationStream() called');
print('isTracking was : $isTracking');
Stream<LatLng> locationStream;
Stream<Position> _positionStream;
LocationOptions locationOptions = LocationOptions(
accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 0);
try {
if (isTracking == true) {
_positionStreamSubsciption.cancel();
} else {
_positionStream = locationManager.getPositionStream(locationOptions);
handleData(Position position, EventSink<LatLng> sink) =>
sink.add(LatLng(position.latitude, position.longitude));
final transformer = StreamTransformer<Position, LatLng>.fromHandlers(
handleData: handleData);
locationStream = _positionStream.transform(transformer);
return locationStream;
}
isTracking = !isTracking;
print('isTracking is : $isTracking');
} catch (error) {
print('startTracking error: $error');
}
}
的 MapState get initialState => LocationStream(locationStream);
@override
Stream<MapState> mapEventToState(MapEvent event) async* {
// user location
if (event is GetLocationStream) {
print('MapBloc event received : $event');
yield* _mapGetLocationStreamToState(event);
}
if (event is LocationUpdated) {
yield* _mapLocationUpdatedToState(event);
}
}
Stream<MapState> _mapGetLocationStreamToState(
GetLocationStream event) async* {
print('_mapGetLocationStreamToState event received : $event');
_locationStreamSubscription =
_mapRepository.getLocationStream().listen((LatLng location) {
locationStream = location;
add(LocationUpdated(locationStream));
print(
'_mapGetLocationStreamToState() locationStream is: $locationStream ');
});
// yield LocationStream(locationStream);
}
中,如果您通过一个块,则实际上是在每次UI重建时都在创建一个新的块。
这对于管理局部值的本地块很有用,但是在我的情况下,BlocBuilder
是在bloc:
中创建的全局块,因此如果我继续在MapBloc
中创建一个新的块,则不会获得该值以最后状态传入,结果为空值。不通过任何集团修复它。
main()
希望这会帮助其他人起步,因为Flutter相对较新,并且关于API的详细解释并不多,因此刚开始时很难掌握。例如,《 Geolocator API参考》非常棒。很明显,对每个类和参数都有详细的解释,并有一些代码示例作为后盾..不需要更多,实现它很容易。flutter_bloc并不是很多(有关此问题,请参见BlocBuilder中的bloc参数),但是可以为您提供满足大部分需求的大量项目,因此无论如何您都会找到理解API的方法。干杯。