I am working on the turn by turn navigation.
Future getReverseGeocodingGivenLatLngUsingMapbox(LatLng latLng) async {
String query = '${latLng.longitude},${latLng.latitude}';
String url = '$baseUrl/$query.json?access_token=$accessToken';
url = Uri.parse(url).toString();
print(url);
try {
_dio.options.contentType = Headers.jsonContentType;
final responseData = await _dio.get(url);
return responseData.data;
} catch (e) {
final errorMessage = DioExceptions.fromDioError(e as DioError).toString();
debugPrint(errorMessage);
}
}
The above function is used below
Future<Map> getParsedReverseGeocoding(LatLng latLng) async {
var response = await getReverseGeocodingGivenLatLngUsingMapbox(latLng);
Map feature = response['features'][0];
Map revGeocode = {
'name': feature['text'],
'address': feature['place_name'].split('${feature['text']}, ')[1],
'place': feature['place_name'],
'location': latLng
};
return revGeocode;
}
And the getParsedReverseGeocoding() function is used below
void initializeLocationAndSave() async {
// Ensure all permissions are collected for Locations
Location _location = Location();
bool? _serviceEnabled;
PermissionStatus? _permissionGranted;
_serviceEnabled = await _location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await _location.requestService();
}
_permissionGranted = await _location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await _location.requestPermission();
}
// Get the current user location
LocationData _locationData = await _location.getLocation();
LatLng currentLocation =
LatLng(_locationData.latitude!, _locationData.longitude!);
// Get the current user address
String currentAddress =
(await getParsedReverseGeocoding(currentLocation))['place']; // getting error over here
// Store the user location in sharedPreferences
sharedPreferences.setDouble('latitude', _locationData.latitude!);
sharedPreferences.setDouble('longitude', _locationData.longitude!);
sharedPreferences.setString('current-address', currentAddress);
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (_) => const Home()), (route) => false);
}
However, I have the following error when the 'place' field is retrieved.
Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
CodePudding user response:
Some things that should help you:
- it seems you're missing jsonDecode and:
Future getReverseGeocodingGivenLatLngUsingMapbox(LatLng latLng) async {
String query = '${latLng.longitude},${latLng.latitude}';
String url = '$baseUrl/$query.json?access_token=$accessToken';
url = Uri.parse(url).toString();
print(url);
try {
_dio.options.contentType = Headers.jsonContentType;
final responseData = await _dio.get(url);
final result = jsonDecode(responseData.data);
return result;
} catch (e) {
final errorMessage = DioExceptions.fromDioError(e as DioError).toString();
debugPrint(errorMessage);
}
}
- it's recommended to use strong typing with Dart, I'm guessing that this should be:
Future<List<dynamic>> getReverseGeocodingGivenLatLngUsingMapbox(LatLng latLng) async {...
}
- And the problem is likely inside the second method:
Future<Map> getParsedReverseGeocoding(LatLng latLng) async {
var response = await getReverseGeocodingGivenLatLngUsingMapbox(latLng);
// This response is likely a List and you don't have key 'features' of type String/index, i.e. you have a index which is supposed to be an int.
// Map feature = response['features'][0];
// Maybe this will work:
Map feature = response[0];
Map revGeocode = {
'name': feature['text'],
'address': feature['place_name'].split('${feature['text']}, ')[1],
'place': feature['place_name'],
'location': latLng
};
return revGeocode;
}
- cascading calls can make your code harder to read and debug:
final revGeocode = await getParsedReverseGeocoding(currentLocation);
final currentAddress = revGeocode['place'];
// now you can hover revGeocode and see what's inside using your IDE
In short: use Dart type system to your favor by strongly typing your code as much as possible.