Я только начинаю с Flutter и все еще не уверен насчет логики c для структурирования классов события / состояния / BLoc / Repositoy для правильного использования этого шаблона. Я застрял при получении значения location
из блока blo c обратно в пользовательский интерфейс при выдаче состояния, которое имеет значение в качестве входного.
Начиная с репозитория у меня есть метод getLocation()
которые получают координаты от Geolocator locationManager
:
Future<LatLng> getLocation() async {
try {
locationManager
.getCurrentPosition(
desiredAccuracy: LocationAccuracy.bestForNavigation)
.timeout(Duration(seconds: 5));
} catch (error) {
print(
'getLocation(): error getting current location: ${error.toString()}');
}
}
, тогда у меня есть событие GetLocation
class GetLocation extends MapEvent {
final LatLng location;
const GetLocation(this.location);
@override
List<Object> get props => [location];
@override
String toString() => 'GetLocation { current location: $location}';
}
, которое отправляется в blo c при загрузке экрана для представления карты, и от кнопки для центрирования карты на пользовательской позиции.
BlocProvider<MapBloc>(create: (context) {
return MapBloc(mapRepository: MapRepository())..add(GetLocation());
}),
затем состояние MapLoaded
, которое содержит местоположение:
class MapLoaded extends MapState {
final LatLng location;
const MapLoaded(this.location);
@override
List<Object> get props => [location];
@override
String toString() => 'MapLoaded {location: $location}';
}
- это виджет, который построен на этом состояние:
BlocBuilder<MapBloc, MapState>(
bloc: MapBloc(mapRepository: _mapRepository),
builder: (BuildContext context, MapState state) {
final LatLng location = (state as MapLoaded).location;
return Container
и, наконец, блок c, где я не могу найти способ передать местоположение в качестве ввода MapState()
в ответ на событие:
class MapBloc extends Bloc<MapEvent, MapState> {
final MapRepository _mapRepository;
StreamSubscription _locationStreamSubscription;
MapBloc(
{@required MapRepository mapRepository,
@required StreamSubscription streamSubscription})
: assert(mapRepository != null || streamSubscription != null),
_mapRepository = mapRepository,
_locationStreamSubscription = streamSubscription;
MapState get initialState => MapLoading();
@override
Stream<MapState> mapEventToState(MapEvent event) async* {
if (event is GetLocation) {
yield* _mapGetLocationToState();
}
if (event is GetTracking) {
yield* _mapGetTrackingToState();
}
if (event is LocationUpdated) {
// CANT GET LOCATION TO PASS IN MapLoaded()
yield MapLoaded();
}
}
Stream<MapState> _mapGetLocationToState() async* {
_mapRepository.getLocation();
(location) => add(LocationUpdated(location));
// CANT GET LOCATION TO PASS IN MapLoaded()
yield MapLoaded(l);
}
Stream<MapState> _mapGetTrackingToState() async* {
_mapRepository.setTracking();
}
}
Внутри Stream<MapState> _mapGetLocationToState()
Я пытался отправить событие add(LocationUpdated(location))
, а в Stream<MapState> mapEventToState
выдать MapLoaded()
, но не могу найти способ пройти в этом месте. Я также пытался выдать его напрямую в Stream<MapState> _mapGetLocationToState()
, но с тем же результатом.
Можете ли вы заметить, что я делаю неправильно? Переключиться на реактивное программирование не так-то просто, но я добираюсь до конца ... Это моя первая попытка использования этого паттерна, и я не полностью сосредоточился на всех концепциях, так что я определенно думал, что некоторые классы ошибочны. Большое спасибо за ваше время и помощь и извините за длинный вопрос. Приветствия.