flutter_map 通过 BLoC 使用地图控制器移动相机

flutter_map move camera with map controller through BLoC

我正在使用 BLoC 模式和 flutter_map 包构建一个 flutter 应用程序。我想将相机移动到特定位置。我正在尝试将地图控制器传递到我的 bloc 结构并从那里移动相机,但我收到错误消息:
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 方法有问题。

我在使用 GetX 时遇到了类似的问题。

我决定应用一些前提:首先,我在 Widget(无状态)中保留了对地图的所有操作 ,因为我需要在 google 插件和 flutter_map.

然后,在控制器中(在你的 BloC 中),它只是触发必要的信息,以便视图从它接收必须居中的新位置,但是视图是知道和集中地图而不是 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) {
  
  }

}

听起来很蠢,但是你在初始化地图控制器吗? 像 MapController mapController = MapController();