#ios #flutter #location #maps
Вопрос:
На моей домашней странице я показываю полноэкранную карту с маркерами, загруженными из базы данных Firestore.
Я использую будущий конструктор для получения некоторых настроек и текущего положения пользователя. Маркеры отображаются в зависимости от расстояния между текущим положением и положением маркера.
Все работает нормально при первом запуске приложения (я использую эмулятор Xcode), но каждый раз при перестроении страницы (например, с горячей перезагрузкой) будущий конструктор застревает, пытаясь получить текущее местоположение, что не работает.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:location/location.dart';
import 'package:map_app/providers/settings_provider.dart';
import 'package:map_app/widget/my_drawer.dart';
import 'package:platform_maps_flutter/platform_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:intl/intl.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Location _location = Location();
late LocationData
_currentPosition; // posizione corrente che verrà calcolata nell'init
bool showProgress = false;
CollectionReference segnalazioni =
FirebaseFirestore.instance.collection('segnalazioni');
Future<LocationData> getCurrentLocation() async {
LocationData currPos; // = await _location.getLocation();
PermissionStatus _permissionGranted;
bool _serviceEnabled;
_serviceEnabled = await _location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await _location.requestService();
if (!_serviceEnabled) {
return Future.error('I servizi di localizzazione non sono abilitati');
}
}
_permissionGranted = await _location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await _location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return Future.error(
'I permessi di accesso alla posizione non sono abilitati');
}
}
// ora recupero la posizione corrente
currPos = await _location.getLocation().timeout(
const Duration(seconds: 5),
onTimeout: () {
print('timeout');
return Future.error('Timeout durante accesso alla posizione');
},
);
currPos = await _location.getLocation();
print('curr location : ${currPos.toString()}');
return currPos;
}
// future utilizzato per caricare le impostazionie
Future<int> loadSettings() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final dist = prefs.getInt('distanza') ?? 1;
return dist;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
drawer: MyDrawer(),
body: FutureBuilder(
future: Future.wait([
loadSettings(),
getCurrentLocation(),
//... More futures
]),
builder: (
context,
// List of dynamic(results of all futures above)
AsyncSnapshot<List<dynamic>> snapshotMultiplo,
) {
// così verifico che TUTTI i future che sto aspettando siano a posto
if (!snapshotMultiplo.hasData) {
return Center(child: CircularProgressIndicator());
}
if (snapshotMultiplo.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
return StreamBuilder<QuerySnapshot>(
stream: segnalazioni.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> markerSnapshot) {
if (!markerSnapshot.hasData) {
return LinearProgressIndicator(); //CircularProgressIndicator();
}
if (markerSnapshot.connectionState ==
ConnectionState.waiting) {
return LinearProgressIndicator(); //CircularProgressIndicator();
}
//print('distanza da settings : ${distanzaSnapshot.data}');
return Consumer<SettingsProvider>(
builder: (context, settings, child) {
return PlatformMap(
myLocationButtonEnabled: true,
myLocationEnabled: true,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(
snapshotMultiplo.data![1].latitude,
snapshotMultiplo.data![1].longitude,
),
zoom: 10),
markers: markerSnapshot.data!.docs.map(
(document) {
print(document.toString());
int distanza = Geolocator.distanceBetween(
// _currentPosition.latitude!,
//_currentPosition.longitude!,
snapshotMultiplo.data![1].latitude,
snapshotMultiplo.data![1].longitude,
document['posizione'].latitude,
document['posizione'].longitude,
).round();
return Marker(
markerId: MarkerId(document.id),
position: LatLng(
double.parse('${document['posizione'].latitude}'),
double.parse(
'${document['posizione'].longitude}'),
),
visible: distanza < settings.diamRicerca * 1000
? true
: false,
infoWindow: InfoWindow(
title: DateFormat('dd-MM-yyyy')
.format(document['data'].toDate())
.toString(),
snippet:
'${document['descrizione']} , distanza = ${Geolocator.distanceBetween( snapshotMultiplo.data![1].latitude,
snapshotMultiplo.data![1].longitude,
document['posizione'].latitude,
document['posizione'].longitude,
).round()}',
),
);
},
).toSet(),
onTap: (location) => print('onTap: $location'),
);
});
});
}),
);
}
}
Я использую конструктор будущего только для получения настроек, текущей позиции и загрузки страницы, а конструктор потоков-для загрузки новых маркеров при их добавлении в Firestore.
На Android все в порядке, поэтому я не совсем понимаю, почему на iOS исследование местоположения работает только в первый раз.
Есть идеи, почему?