Флаттер Blo c. Я не могу получить значение для передачи в состоянии, которое я получаю в mapEventToState () ` - PullRequest
0 голосов
/ 26 февраля 2020

Я только начинаю с 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(), но с тем же результатом.

Можете ли вы заметить, что я делаю неправильно? Переключиться на реактивное программирование не так-то просто, но я добираюсь до конца ... Это моя первая попытка использования этого паттерна, и я не полностью сосредоточился на всех концепциях, так что я определенно думал, что некоторые классы ошибочны. Большое спасибо за ваше время и помощь и извините за длинный вопрос. Приветствия.

1 Ответ

1 голос
/ 26 февраля 2020

Ваш _mapGetLocationToState() не имеет события в качестве параметра.

@override
  Stream<MapState> mapEventToState(MapEvent event) async* {
    if (event is GetLocation) {
      yield* _mapGetLocationToState(event);
    }

    if (event is GetTracking) {
      yield* _mapGetTrackingToState();
    }

    if (event is LocationUpdated) {
    // CANT GET LOCATION TO PASS IN MapLoaded()
      yield MapLoaded();
    }
  }

  Stream<MapState> _mapGetLocationToState(GetLocation event) async* {
    // now you have event.location
    _mapRepository.getLocation();


    (location) => add(LocationUpdated(location));
    // CANT GET LOCATION TO PASS IN MapLoaded(event.location)
    yield MapLoaded(event.location);

  }

  Stream<MapState> _mapGetTrackingToState() async* {
    _mapRepository.setTracking();
  }
}

РЕДАКТИРОВАТЬ: BlocProvider Задача состоит в создании экземпляра класса Blo c, который вы хотите иметь. В этом случае MapBloc. Как видите, ваш класс MapBloc имеет 2 зависимости: MapRepository и StreamSubscription. Поэтому, когда BlocProvider хочет сделать экземпляр этого, вы должны предоставить те вещи, которые ему нужны, через конструктор. То же самое, что и GetLocation, вам нужно указать LatLng, потому что это зависит от него.

BlocProvider<MapBloc>(create: (context) {
  return MapBloc(
           mapRepository: MapRepository(),
           streamSubscription: ...?
         )..add(GetLocation(...?));
}),
...