I am building a flutter map app with the flutter_map.
When the device is ready, I want to fetch the location and move the map to the location.
However, I'm having issues with my code. I'm not sure what I did wrong.
I got the error:
The getter 'onReady' isn't defined for the type 'MapController'.
Below are my codes:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:spot_the_bird/bloc/location_cubit.dart';
import 'package:spot_the_bird/screens/map_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<LocationCubit>(
create: (context) => LocationCubit()..getLocation(),
),
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
appBarTheme: const AppBarTheme(backgroundColor: Color(0xff1746A2)),
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.deepOrange),
),
initialRoute: "/",
routes: {
"/": (context) => MapScreen(),
},
),
);
}
}
Map screen
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:spot_the_bird/bloc/location_cubit.dart';
class MapScreen extends StatelessWidget {
MapScreen({super.key});
final MapController _mapController = MapController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: BlocListener<LocationCubit, LocationState>(
listener: (prevState, currState) {
if (currState is LocationError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(currState.message),
duration: const Duration(seconds: 3),
backgroundColor: Theme.of(context).errorColor,
),
);
}
if (currState is LocationLoaded) {
_mapController.onReady.then((value) => _mapController.move(
LatLng(currState.latitude, currState.longitude), 15));
// This is where I got the error
}
},
child: FlutterMap(
mapController: _mapController,
options: MapOptions(
center: LatLng(51.509364, -0.128928),
zoom: 15,
minZoom: 4,
),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: const ['a', 'b', 'c'],
retinaMode: true,
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<LocationCubit>().getLocation();
},
child: const Icon(Icons.navigation_outlined),
),
);
}
}
STATE MANAGEMENT THROUGH BLOC
Location Cubit
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:geolocator/geolocator.dart';
part 'location_state.dart';
class LocationCubit extends Cubit<LocationState> {
LocationCubit() : super(const LocationInitial());
Future<void> getLocation() async {
LocationPermission locationPermission = await Geolocator.checkPermission();
if (locationPermission != LocationPermission.denied ||
locationPermission != LocationPermission.deniedForever) {
emit(const LocationLoading());
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);
emit(LocationLoaded(
longitude: position.longitude, latitude: position.latitude));
} catch (error) {
emit(const LocationError(
message: 'Error occured while fetching location'));
}
} else {
Geolocator.requestPermission();
}
}
}
Location_state.dart
part of 'location_cubit.dart';
abstract class LocationState extends Equatable {
const LocationState();
@override
List<Object?> get props => [];
}
class LocationInitial extends LocationState {
const LocationInitial();
}
class LocationLoading extends LocationState {
const LocationLoading();
}
class LocationLoaded extends LocationState {
const LocationLoaded({
required this.longitude,
required this.latitude,
});
final double longitude;
final double latitude;
@override
List<Object?> get props => [latitude, longitude];
}
class LocationError extends LocationState {
final String message;
const LocationError({
required this.message,
});
}
Dependencies in pubspec.yaml
dependencies:
flutter:
sdk: flutter
flutter_map: ^3.0.0
latlong2: ^0.8.1
geolocator: ^9.0.2
flutter_bloc: ^8.1.1
equatable: ^2.0.5
bloc: ^8.1.0
cupertino_icons: ^1.0.2
CodePudding user response:
2 options:
- You can use the 2.2.0 version, onReady is removed in 3.0 (see Changelogs)
- Try the onMapReady Callback in the 3.0 version
https://pub.dev/packages/flutter_map/changelog
https://github.com/fleaflet/flutter_map/pull/1333
https://docs.fleaflet.dev/migration/to-v3.0.0#removed-mapcontroller-.onready