Я все еще очень плохо знаком с Flutter / Dart и использую шаблон flutter_blo c bloc / repository. Я изо всех сил пытаюсь получить значение из метода репозитория обратно в методе blo c. Мой первый подход ( Я получаю нулевое возвращаемое значение из метода. Flutter ) состоял в том, чтобы прослушать Stream<Position>
в методе репозитория и вернуть LatLng
, который я получил бы в своем блоке c method..I всегда получает значение 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');
}
}
blo c:
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));
.
В блоке c Мне также пришлось прослушивать поток местоположения с _mapRepository.getLocationStream()
. Теперь, поскольку вывод состояния непосредственно из области прослушивателя невозможен, а вывод его из-за пределов областей просто возвращает текущее значение потока и не обновляется после этого, мне пришлось использовать цикл событий. Я добавил к событию blo c a LocationUpdated
, проходящему в месте из потока.
в blo cs
mapEventToState I had to react to that event yielding the
LocationStream` вместе с местоположение.
Теперь состояния текут, как и ожидалось, с новым значением местоположения вместе с ними.
Единственная проблема, которую осталось решить (которую я на самом деле думал, что не сделал есть) это то, что MapScren
BlocBuilder
не получает значение, поступающее из нового состояния, и я получаю нулевое значение при его использовании, как в _mapController.move(userLocation, 16);
.
Не является ли LatLng userLocation = (state as LocationStream).location;
правильным способ получить его?
Обновленный код:
BlocBuilder:
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');
}
}
blo c:
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);
}