flutter_map перемещает камеру с контроллером карты через BLoC

Я создаю приложение флаттера, используя шаблон BLoC и пакет flutter_map. Я хочу переместить камеру в определенное положение. Я пытаюсь передать контроллер карты в структуру своего блока и переместить камеру оттуда, но получаю сообщение об ошибке:
NoSuchMethodError: The getter 'onReady' was called on null.
Я не уверен, что это правильный подход.

class HomePage extends StatelessWidget {
  const HomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
        providers: [
          ...,
          BlocProvider<MapBloc>(
            create: (BuildContext context) => MapBloc(mapController: MapController()) // passing map controller
            ..add(MapDataInit()),
          )
        ],
          ...
     );
  }
}

map_bloc.dart

class MapBloc extends Bloc<MapEvent, MapState> {
  final MapController mapController;
  LocationRepository _locationRepository = LocationRepository();

  MapBloc({@required this.mapController});

  @override
  get initialState => MapDataUninitialized();

  @override
  Stream<MapState> mapEventToState(MapEvent event) async* {
    final currentState = state;

    if (event is AddMarker) {
      yield MapDataLoaded(
          mapController: this.mapController,
          markers: [...]);
        this.add(MoveCamera(event.latLan)); // not sure about this
    }
    if (event is MoveCamera) {
      mapController.onReady.then((result) { // i'm getting an error here
        mapController.move(event.latLan, 15.0);   
      });
    }
  }
}


Виджет с картой

class SelectLocationView extends StatelessWidget {
  Widget build(BuildContext context) {
    return BlocBuilder<MapBloc, MapState>(
          builder: (context, state) {
            ...
            if (state is MapDataLoaded) {
              return Container(
                child: Center(
                    child: Container(
                        child: FlutterMap(
                          mapController: state.mapController, // I'm trying to get previously defined controller
                  options: MapOptions(...),
                  layers: [
                    TileLayerOptions(
                        urlTemplate:
                            "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                        subdomains: ['a', 'b', 'c']),
                    MarkerLayerOptions(...),
                  ],
                ))),
              );
            }
          },
        );
  }
}

Понятия не имею, почему у контроллера карты проблема с методом onReady.


person Adren echo    schedule 11.04.2020    source источник


Ответы (2)


У меня была аналогичная проблема с GetX.

Я решил, применив некоторые предпосылки: во-первых, я сохранил в виджете (без сохранения состояния) любые манипуляции с картой , потому что мне нужно переключаться между плагином Google и flutter_map.

Затем в контроллере (в вашем случае в BloC) он просто запускает необходимую информацию, чтобы представление получило от него новое местоположение, которое должно быть центрировано, но представление - это тот, кто знает и кто централизует карту, а не Блок.

Короче говоря, мне пришлось работать со статической переменной, чтобы сохранить одноэлементную ссылку на mapController в приложении, потому что метод onReady () был вызван только один раз, и поэтому я сохранил bool для управления состоянием карты, тогда как onReady он не выполняется, у нас нет доступа к объектам карты, таким как масштабирование и перемещение.

Мой пример кода:

class FlutterMapWidget extends StatelessWidget {

  static MapController _mapController;
  bool isMapRead = false;

  FlutterMapWidget() {
    // create instance only not exists another reference
    if(_mapController == null) {
      _mapController = MapController();
    }
    
    // after onReady, flag local control variable
    _mapController.onReady.then((v) {
      isMapRead = _mapController.ready;
    });
  }
  
  @override
  Widget build(BuildContext context) {

    return  Stack(
      children: [
        _buildMap(),
        // add another map components ...
      ],
    );

  }
  
  void _gotoLocation(double lat,double long) {
    //check if map is ready to move camera...
    if(this.isMapRead) {
      _mapController.move(LatLng(lat, long), _mapController?.zoom);
    }
  }

  Widget _buildMap(){

    return GetBuilder<MapEventsController>( // GetX state control
      init: _mapEventsController, // GetX events controller
      builder: (value) { // GetX event fire when update state in controller

        updatePinOnMap(value.liveUpdate, value.location);

        if(value.liveUpdate){
          _gotoLocation(value.location.lat, value.location.lng);
        }

        return FlutterMap(
          mapController: _mapController,
          options: MapOptions(
            center: LatLng(value?.location?.lat, value?.location?.lng),
            zoom: 13.0,
            plugins: [
            ],
            onTap: _handleTap,
          ),
          layers: [
            TileLayerOptions(
                urlTemplate:
                'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                subdomains: ['a', 'b', 'c']
            ),
            MarkerLayerOptions(markers: markers), //markers
          ],
        );
      },
    );

  }

  void updatePinOnMap(bool liveUpdate, Location location) async {

    if(location == null) {
      return;
    }


    this.markers.clear();

    Marker mark = Marker(
      point: LatLng(location.lat, location.lng),
      anchorPos: anchorPos,
      builder: (ctx) =>
        GestureDetector(
          onTap: () => _configureModalBottomSheet(ctx),
          child: Container(
            child: Icon(Icons.my_location, size: 28, color: Colors.red,), // FlutterLogo(),
          ),
        ),
    );

    markers.add(mark);

  }

  void _handleTap(LatLng latlng) {
    
  }
  
  void _configureModalBottomSheet(context) {
  
  }

}
person Wedson Quintanilha da Silva    schedule 15.10.2020

Звучит глупо, но вы инициализируете контроллер карты? Нравится MapController mapController = MapController ();

person Kishan Kumar    schedule 05.11.2020