Ich versuche, eine einfache Kartenfunktionalität in meiner Flutter iOS-Anwendung zu implementieren. Ich habe die Anleitungen befolgt, angefangen von der Readme-Datei zum Flutter-Standortpaket über den Artikel "Implementieren Sie Echtzeit-Standortaktualisierungen auf Google Maps in Ihren Flutter-Apps" bis hin zu vielen Stapelfragen zu ähnlichen Problemen.
Das Problem ist, dass ich den aktuellen Standort vor dem Laden der Karten nicht abrufen kann und daher seine LatLng- initialCameraPosition
Ergebnisse in NPE erhalten. Was ich tun kann, ist das Laden der Karten mit fest codierten initialCameraPosition
, der aktuelle Standort wird dann korrekt geladen und ich kann die Kamera entweder durch Ziehen oder durch Klicken auf die Schaltfläche für den schwebenden Standort in der rechten unteren Ecke dorthin verschieben.
Hier ist mein Codebeispiel:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
const double CAMERA_ZOOM = 16;
const LatLng SOURCE_LOCATION = LatLng(37.3317, -122.0325086);
class MapPage extends StatefulWidget {
@override
_MapPageState createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
GoogleMapController mapController;
LocationData currentLocation;
Location location;
bool _serviceEnabled;
PermissionStatus _permissionGranted;
@override
void initState() {
super.initState();
location = new Location();
location.onLocationChanged.listen((event) {
currentLocation = event;
});
setInitialLocation();
}
void setInitialLocation() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
currentLocation = await location.getLocation();
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
CameraPosition initialCameraPosition() {
LatLng target;
if (currentLocation != null)
target = LatLng(currentLocation.latitude, currentLocation.longitude);
else
target = SOURCE_LOCATION;
return CameraPosition(target: target, zoom: CAMERA_ZOOM);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.orangeAccent,
title: Text('Map'),
centerTitle: true,
),
body:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: initialCameraPosition(),
myLocationEnabled: true,
),
);
}
}
Ich verstehe, dass das Abrufen des aktuellen Standorts ein asynchroner Prozess ist, daher habe ich auch versucht, dies FutureBuilder
im Body-Abschnitt zu verwenden:
FutureBuilder<LocationData>(
future: currentLocation,
builder: (context, snapshot) {
if (snapshot.hasData) {
LocationData currentLocation = snapshot.data;
return GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(
currentLocation.latitude, currentLocation.longitude)),
myLocationEnabled: true,
);
} else if (snapshot.hasError) {
return (Text("${snapshot.error}"));
}
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.orangeAccent,
),
);
},
),
was wie ein Zauber funktionierte, als ich Daten aus einer HTTP-GET-Anfrage abrufen musste, aber diesmal führt es nur zu einer endlosen CircularProgressIndicator
.
Ich habe viele andere Lösungen von Stack-Fragen ausprobiert, einschließlich der Rückgabe von leer, Container
wenn currentLocation
null ist, und das Erstellen von Bedingungen für FutureBuilder snapshot.connectionState
, erneut ohne Erfolg.
Das Lustige ist, dass ich, als ich tiefer in die Location.getCurrentLocation()
Methode eintauchte, Folgendes fand:
/// Gets the current location of the user.
///
/// Throws an error if the app has no permission to access location.
/// Returns a [LocationData] object.
Future<LocationData> getLocation() async {
return LocationPlatform.instance.getLocation();
}
die geht dann an:
/// Gets the current location of the user.
///
/// Throws an error if the app has no permission to access location.
/// Returns a [LocationData] object.
Future<LocationData> getLocation() {
throw UnimplementedError();
}
Das lässt mich zweifeln, ob dieses Plugin überhaupt funktioniert.
Hier ist mein flutter doctor -v
Ergebnis:
[✓] Flutter (Channel master, v1.18.0-6.0.pre.82, on Mac OS X 10.15.4 19E287, locale pl-PL)
• Flutter version 1.18.0-6.0.pre.82 at /Users/Vuco/flutter
• Framework revision f35b673f2b (26 hours ago), 2020-04-19 02:45:01 +0530
• Engine revision a5e0b2f2f2
• Dart version 2.9.0 (build 2.9.0-1.0.dev 5b19445d9c)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
• Android SDK at /Users/Vuco/Library/Android/sdk
• Platform android-29, build-tools 29.0.3
• Java binary at: /Users/Vuco/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/192.6308749/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.4.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.4.1, Build version 11E503a
• CocoaPods version 1.9.1
[✓] Android Studio (version 3.6)
• Android Studio at /Users/Vuco/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/192.6308749/Android Studio.app/Contents
• Flutter plugin version 45.0.1
• Dart plugin version 192.7761
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
[!] IntelliJ IDEA Ultimate Edition (version 2020.1)
• IntelliJ at /Users/Vuco/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
• For information about installing plugins, see
https://flutter.dev/intellij-setup/#installing-the-plugins
[✓] VS Code (version 1.44.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.9.1
[✓] Connected device (1 available)
• iPhone 8 • F60856B8-2C6E-401D-A0F9-06FFC7E09876 • ios • com.apple.CoreSimulator.SimRuntime.iOS-13-4 (simulator)
! Doctor found issues in 1 category.
und die Abhängigkeiten die ich verwende:
google_maps_flutter: ^0.5.25+3
location: ^3.0.2
Das Problem, dass Sie Ihre Karte rendern, bevor Sie Ihre Ausgangsposition haben, von der ich glaube, dass Sie wissen, dass dies FutureBuilder
funktionieren würde, aber möglicherweise übertrieben ist. Alles, was Sie wirklich brauchen, ist ein Boolean.
GoogleMapController mapController;
LocationData currentLocation;
Location location;
bool _serviceEnabled;
PermissionStatus _permissionGranted;
CameraPosition _center =
CameraPosition(target: SOURCE_LOCATION, zoom: CAMERA_ZOOM);
bool isLoading = false;
@override
void initState() {
super.initState();
location = new Location();
_getLocation();
}
_getLocation() async {
setState(() {
isLoading = true;
});
initialize();
currentLocation = await location.getLocation();
if (currentLocation == null) {
return;
}
_center = CameraPosition(
target: LatLng(currentLocation.latitude, currentLocation.longitude),
zoom: CAMERA_ZOOM);
setState(() {
isLoading = false;
});
print("CurrentLocation: $currentLocation");
}
Future<void> initialize() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.DENIED) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.GRANTED) {
return;
}
}
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.orangeAccent,
title: Text('Map'),
centerTitle: true,
),
body: isLoading
? CircularProgressIndicator()
: Container(
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: _center,
myLocationEnabled: true,
),
),
);
}
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen