flutter NoSuchMethodError: The getter 'lat' was called on null - flutter

When searching through Google Maps, a function that returns a location is used, and null is called.
The placeDetail class is initialized and used, but I don't know what the problem is.
void _moveCamera() async {
try{
GoogleMapController controller = await _mapController.future;
controller.animateCamera(
CameraUpdate.newLatLng(
LatLng(
placeDetail.lat,
placeDetail.lng)),
);
} catch(e) {
print("error?? -$e");
}
print("noo - ${placeDetail.lat}");
print("noo - ${placeDetail.lng}");
setState(() {
_markers.add(
Marker(
markerId: MarkerId(placeDetail.name),
position: LatLng(placeDetail?.lat, placeDetail.lng),
infoWindow: InfoWindow(
title: placeDetail.name,
snippet: placeDetail.formattedAddress),
));
});
}
json을 받아온 부분은 문제가 없는 걸로 생각됩니다.
formatted_address: 대한민국 서울특별시 은평구 응암동, geometry: {location: {lat: 37.5942526, lng: 126.9185857}, 이렇게 출력이됩니다.
I initialized it here.
void getCurrentPosition() async {
LocationData pos = await location.getLocation();
setState(() {
currentPos = LatLng(
pos.latitude,
pos.longitude,
);
});
placeDetail = PlaceDetail(lng: pos.longitude, lat: pos.latitude);
print('google mapff - ${currentPos.latitude}');
GoogleMapController mapCtrl = await _mapController.future;
mapCtrl.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
currentPos.latitude,
currentPos.longitude),
zoom: zoomLevel),
),
);
}

Where have you defined placeDetail ? You have to make sure placeDetail is within the scope of the code being executed.

Related

How to set a custom image as icon for gmap marker in flutter?

I wanted to add some markers in a gmap on flutter I made. I tried this code but it doesn't work. I have added link in pubspec and picture is in assets too.
Future<void> addMarker(
LatLng mLatLng, String mTitle, String mDescription) async {
BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(),
"assets/images/icons/pin.png",
);
setState(() async {
_markers.clear();
_markers.add(Marker(
markerId:
MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: markerbitmap //BitmapDescriptor.defaultMarker,
));
});
}
no marker gets addded on the map but shows this error in debug console
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception:
setState() callback argument returned a Future. E/flutter ( 7655): The
setState() method on _HomePageState#3d9e4 was called with a closure or
method that returned a Future. Maybe it is marked as "async".
E/flutter ( 7655): Instead of performing asynchronous work inside a
call to setState(), first execute the work (without updating the
widget state), and then synchronously update the state inside a call
to setState(). E/flutter ( 7655): #0 State.setState. package:flutter/…/widgets/framework.dart:1112 E/flutter (
7655): #1 State.setState
package:flutter/…/widgets/framework.dart:1128 E/flutter ( 7655): #2
_HomePageState.addMarker package:mymapp/screens/home_page.dart:417 E/flutter ( 7655): E/flutter ( 7655):
E/MethodChannel#plugins.flutter.dev/google_maps_android_0( 7655):
Failed to handle method call
You should do this in initState
final _controller = Completer<GoogleMapController>();
var _markers = const <Marker>{};
Set<Marker> get markers => _markers;
set markers(Set<Marker> val) {
setState(() => _markers = val);
}
...
#override
void initState() {
initializeMap();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
...
markers: markers,
...
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
);
}
...
void initializeMap(){
markers = {
Marker(
markerId: MarkerId(UniqueKey().toString()),
icon: await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(),
'assets/images/icons/pin.png',
),
position: target.target,
rotation: target.tilt,
)
};
}
you have this error because you are trying to use "Async" in the block of a setState.
you can remove the async and modify your code to this:
Future<void> addMarker(
LatLng mLatLng, String mTitle, String mDescription) async {
BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(),
"assets/images/icons/pin.png",
);
setState(() *** ----- delete the async here {
_markers.clear();
_markers.add(Marker(
markerId:
MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: markerbitmap //BitmapDescriptor.defaultMarker,
));
});
}
I DID THIS.
First, create a method that handles the asset path and receives a size (this can be either the width, height, or both, but using only one will preserve ratio).
import 'dart:ui' as ui;
Future<Uint8List> getBytesFromAsset(String path, int width) async {
ByteData data = await rootBundle.load(path);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
ui.FrameInfo fi = await codec.getNextFrame();
return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
}
Then, just add it to your map using the right descriptor:
final Uint8List markerIcon = await getBytesFromAsset('assets/images/flutter.png', 100);
final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));
REF: How to change the icon size of Google Maps marker in Flutter?

Flutter walk & draw polylines following current location

Using flutter_polyline_points: ^1.0.0 & google_maps_flutter: ^2.2.1
So what I am trying to achieve is to draw polylines on Google Map at flutter following current WALKING user location [using Geolocator]. The code below works, except when I stay out of the road, polylines are not drawn after my location [the location of blue dot at google maps] but they stick to the main road and won't cross it's boundaries...
(https://i.stack.imgur.com/FHV2d.jpg)
CountDown func is counting down to 0 and then showing map/location/timer etc [start walk]
_CountDown() async {
const oneSec = Duration(seconds: 1);
_timer = Timer.periodic(oneSec, (timer) {
_startTimer == 0
? setState(
() {
timer.cancel();
_getCurrentLocation();
Future.delayed(const Duration(seconds: 5), () {
stopWatchTimer.onStartTimer();
_updateMapAndValues();
});
},
)
: setState(
() => _startTimer--,
);
});
}
_getCurrentLocation() is getting current position and sets late _currectPosition to later zoom on it with map.
_getCurrentLocation() async {
await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best,
forceAndroidLocationManager: true)
.then((Position position) async {
setState(() {
_currentPosition = position;
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 18.0,
),
),
);
});
}).catchError((e) {
print(e);
});
}
After that I am stopping the timer/updating the map.
First I am getting current position to check if location changed, then I am creating polyline between old _currentposition and new position (later calc distance and coins but that's not that importand).
_updateMapAndValues() async {
bool petla = true;
while (petla) {
await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best,
forceAndroidLocationManager: true)
.then((Position position) async {
await Future.delayed(const Duration(milliseconds: 500));
if (_currentPosition.latitude != position.latitude &&
_currentPosition.longitude != position.longitude) {
_createPolylines(_currentPosition, position);
await _calculateDistance();
setState(() {
_currentPosition = position;
int result = distance * 1000 ~/ 50;
print('DYSTANS ILE COINOW : $result');
if (result > 0) {
while (coins < result) {
setState(
() => coins++,
);
}
}
});
}
});
}
}
The _createPolylines function. I thought it will work adding travelMode:walking but it does not. Still (mostly) following the roads and when I am moving at the edges (screen) it just draw straight line.
late PolylinePoints polylinePoints;
List<LatLng> polylineCoords = [];
Map<PolylineId, Polyline> polylines = {};
_createPolylines(Position start, Position end) async {
polylinePoints = PolylinePoints();
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
'AIzaSyDDyBb0N9_jthBS99PRJcT6CjFV2TI9J5E',
PointLatLng(start.latitude, start.longitude),
PointLatLng(end.latitude, end.longitude),
travelMode: TravelMode.walking,
avoidHighways: true,
);
if (result.points.isNotEmpty) {
result.points.forEach((element) {
polylineCoords.add(LatLng(element.latitude, element.longitude));
print('--------WYSWIETLAM: $polylineCoords');
});
}
PolylineId id = const PolylineId('poly');
Polyline polyline = Polyline(
polylineId: id,
color: Colors.red,
points: polylineCoords,
width: 5,
);
polylines[id] = polyline;
}

The operator '[]' isn't defined for the type 'Future<Map<String, dynamic>>'

I am getting this error and do not know how to solve it:
var directions = LocationService().getDirections(
_originController.text, _destinationController.text);
_goToPlace(directions['start_location']['lat'], directions['start_location']['lng']);
setPolyline(directions['polyline_decoded']);
},
Below is the code of the _goToPlace() method:
Future<void> _goToPlace(double lat, double lng) async {
final GoogleMapController controller = await _controllerGoogleMap.future;
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(lat, lng),
zoom: 12,
),
),
);
}
Mark your function as async and put an await before your getDirections
await LocationService().getDirections(
_originController.text, _destinationController.text);
Your getDirections returns a Future, so you have await it.

Flutter converting variable to Lat & Lng

i have function which gets user phone location, and i want to set Marker on this location.
The question is :
How i can type to LatLng() location of user's phone.
What i tried? :
When i type there var locationMessage there is an error:
2 positional argument(s) expected, but 1 found
void getCurrentLocation() async {
var position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
var lastPosition = await Geolocator.getLastKnownPosition();
print(lastPosition);
setState(() {
locationMessage = "${position.altitude}, ${position.longitude}";
});
}
GoogleMap(
markers: _markers,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
setState(() {
_markers.add(Marker(
icon: mapMarker,
markerId: const MarkerId("marker-1"),
position: LatLng(//HOW TO INSERT HERE USER'S LOCATION)));
});
},
),
Instead of declaring locationMessage with String type use Position type.
so instead of
var position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
replace with
locationMessage = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
Then here
........
........
........
setState(() {
_markers.add(Marker(
icon: mapMarker,
markerId: const MarkerId("marker-1"),
position: LatLng(locationMessage.latitude, locationMessage. longitude)));///PASS LAT AND LONG
});
........
........
........
I would suggest doing something like this:
create _currentLocation var:
LatLng _currentLocation;
update value inside getCurrentLocation() / setState():
_currentLocation = LatLng(position.latitude, position.longitude);
inside _markers.add use:
position: _currentLocation
You should initialize _currentLocation value inside initState() by calling getCurrentLocation():
#override
void initState() {
getCurrentLocation();
super.initState();
}
Note: if you are using google_maps_flutter package and you want to show the user position, you can set the myLocationEnabled property to true:
GoogleMap(
myLocationEnabled: true,
...

flutter How to get markers from API and show on map

I make a simple app in flutter to get markers from API and draw them on Google Map.
I make a model with Location name and I have get markers information from the API and added them to the list of markers.
But when I run my app, no markers shown on map.
How can I solve this problem?
My function That get markers from API :
Future<List<Location>> getLocations() async {
try {
var url = 'http://10.0.2.2/Track_App/locations.php';
final resp = await http.get(url);
final responsebody = jsonDecode(resp.body);
return responsebody; //this return a list
} catch (e) {
return [];
}
}
List<Marker> allMarkers = [];
loadLocations() async {
List<Location> locations;
locations = [];
locations = await getLocations(); //we store the response in a list
for (var i = 0; i < locations.length; i++) {
LatLng latlng;
latlng = LatLng(
double.parse(locations[i].locX),
double.parse(locations[i].locY),
);
allMarkers.add(
Marker(
markerId: MarkerId(locations[i].locId.toString()),
position: latlng,
),
);
}
setState(() {});
}
Google Map Code :
FutureBuilder(
future: loadLocations(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
markers: snapshot.data,
);
},
),
JSON data from API :
[
{
loc_id: "1 ",
loc_x: "15.392567",
loc_y: "44.278188"
},
{
loc_id: "2 ",
loc_x: "15.391717",
loc_y: "44.278019"
}
]
My Model :
class Location {
Location({
this.locId,
this.locX,
this.locY,
this.locInfo,
this.locSpd,
this.locDate,
});
String locId;
String locX;
String locY;
String locInfo;
String locSpd;
String locDate;
factory Location.fromJson(Map<String, dynamic> json) => Location(
locId: json['loc_id'],
locX: json['loc_x'],
locY: json['loc_y'],
locInfo: json['loc_info'],
locSpd: json['loc_spd'],
locDate: json['loc_date'],
);
Map<String, dynamic> toJson() => {
'loc_id': locId,
'loc_x': locX,
'loc_y': locY,
'loc_info': locInfo,
'loc_spd': locSpd,
'loc_date': locDate,
};
}
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
Whenever, you want to add maker here, create a new Marker and add to State
Marker marker = Marker(...)
setState(() {
markers[markerId] = marker;
});
And your build function would just be like this
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: const CameraPosition(
target: LatLng(-33.852, 151.211),
zoom: 11.0,
),
markers: Set<Marker>.of(markers.values),
),
this code work for me just change your location listner
Future<Offre> location_client() async{
var _loc = await _location.getLocation();
setState(() {
client_lat = _loc.client.lat;
client_lng = _loc.client.lng;
print("test test"+_loc.client.lat.toString()+','+_loc.client.lng.toString());
LatLng latlng = LatLng(client_lat,client_lng);
setState(() {
_markers.add(Marker(
markerId: const MarkerId("home"),
position: latlng,
draggable: false,
zIndex: 2,
flat: true,
anchor: const Offset(0.5, 0.5),
icon: BitmapDescriptor.defaultMarker));
});
});
}