Slow display of the map
Hello,
It takes typically 4 to 5 seconds to build and display the map. I'm using version 0.42.0. Is there a way to speed up the display ? Alternatively, is there a way to build the map once for all and speed up the next displays (caching the tiles) ? Many thanks for your support, please find my code here-below:
/// ********************************************************************** /// Backup version with no live reaction to shelter list modification /// **********************************************************************
import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_osm_plugin/flutter_osm_plugin.dart'; import 'package:geolocator/geolocator.dart'; import 'package:provider/provider.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; //import 'view_shared_photos.dart'; import 'package:collection/collection.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import '../../Services/location.dart'; import 'package:flutter/foundation.dart'; import '../../Model/camera.dart'; import '../../Services/photo_service.dart'; import 'view_shared_photos.dart';
class ViewCamerasMap extends StatefulWidget { const ViewCamerasMap({Key? key}) : super(key: key);
@override _ViewCamerasMapState createState() => _ViewCamerasMapState(); }
class _ViewCamerasMapState extends State<ViewCamerasMap> with OSMMixinObserver {
late CustomController controller;
late GlobalKey<ScaffoldState> scaffoldKey;
Key mapGlobalkey = UniqueKey();
ValueNotifier
late double latitude; late double longitude;
bool _mapIsReady = false; List<Camera> _sharedCameras = []; List<GeoPoint> _markersList = []; late GeoPoint _userLocation;
Stopwatch stopwatch = new Stopwatch();
/// ********************************************************************** /// init - Executed only 1 time before display /// ********************************************************************** @override void initState() { print("ViewCameraMap - initState - start"); stopwatch.start(); super.initState();
controller = CustomController(initMapWithUserPosition: true);
controller.addObserver(this);
//controller.enableTracking();
getUserLocation();
scaffoldKey = GlobalKey<ScaffoldState>();
_getSharedCamerasList();
print("ViewCameraMap - initState - end - ${stopwatch.elapsedMilliseconds}");
}
Future getUserLocation() async { // Set Paris coordinates by default double latitude = 48.866; double longitude = 2.333;
final location = Location();
await location.getLocation()
.then((value) {
latitude = value.latitude;
longitude = value.longitude;
})
.onError((error, stackTrace) {
// Returns Paris coordinates by default
print("onShelterClicked - getUserLocation - error = $error");
});
_userLocation = GeoPoint(latitude: latitude, longitude: longitude);
print("ViewCameraMap - getUserLocation - ${stopwatch.elapsedMilliseconds}");
}
Future
}
/// ********************************************************************** /// Build /// ********************************************************************** @override Widget build(BuildContext context) { print("ViewCameraMap - build - start - ${stopwatch.elapsedMilliseconds}");
return Scaffold(
key: scaffoldKey,
resizeToAvoidBottomInset: false,
appBar: appBar(context),
floatingActionButton: (_mapIsReady)
? gotoMyPosition(context)
: null,
body: Container(
child: Stack(
children: [
OSMFlutter(
controller: controller,
trackMyPosition: false,
androidHotReloadSupport: true,
showZoomController: true,
mapIsLoading: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text((AppLocalizations.of(context) == null)
? "Map is loading..."
: AppLocalizations.of(context)!.viewCamerasMapIsLoading),
],
),
),
onMapIsReady: (isReady) {
if (isReady) {
print("ViewCameraMap - build/onMapIsReady - ${stopwatch.elapsedMilliseconds}");
setState(() {
_mapIsReady = true;
});
}
},
/// Handling click on marker
onGeoPointClicked: (geoPoint) {
onShelterClicked(geoPoint);
},
),
],
),
),
);
}
/// ********************************************************************** /// Top application bar /// ********************************************************************** AppBar appBar(BuildContext context) { return AppBar( title: Text((AppLocalizations.of(context) == null) ? "Shared cameras" : AppLocalizations.of(context)!.viewCamerasMapTitle),
);
}
/// ********************************************************************** /// Show user's position on the map /// ********************************************************************** FloatingActionButton gotoMyPosition(BuildContext context) { return FloatingActionButton( onPressed: () async { print("onShelterClicked - gotoMyPosition - await current location"); await controller.goToLocation(_userLocation); //await controller.setZoom(zoomLevel: 10); setState(() { }); }, child: const FaIcon(FontAwesomeIcons.locationCrosshairs), ) ; }
/// ********************************************************************** /// Handle click on shelter => goto display the shelter shared images /// ********************************************************************** void onShelterClicked(GeoPoint geoPoint) {
print("ViewCamerasMap - onShelterClicked - geoPoint = $geoPoint");
//final sharedSheltersList = Provider.of<PhotoService>(context, listen: false).sharedSheltersList;
try {
// Find the clicked shelter
Camera? clickedCamera = _sharedCameras.firstWhereOrNull((camera) =>
(double.parse(camera.latitude!) == geoPoint.latitude) &&
(double.parse(camera.longitude!) == geoPoint.longitude));
if (clickedCamera != null) {
// Display the page
print("ViewCamerasMap - onShelterClicked - Selected camera ID = ${clickedCamera.cameraID}");
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) => ViewSharedPhotos(camera: clickedCamera)));
} else {
print("ViewCamerasMap - onShelterClicked - No camera found under the click");
}
} catch (e) {
print("error $e");
}
}
/// **********************************************************************
/// Prepare the map with markers
/// **********************************************************************
@override
Future
Future
await controller.setZoom(zoomLevel: 2.1);
final bounds = await controller.bounds;
print(bounds.toString());
// Set up all shared shelters as geo point to be displayed
await _buildCamerasGeoPoint();
print("ViewCameraMap - mapIsInitialized - end - ${stopwatch.elapsedMilliseconds}");
}
Future
// Remove all markers
if (_markersList.isNotEmpty) {
_markersList.forEach( (marker) async {
await controller.removeMarker(marker);
});
}
_sharedCameras.forEach((camera) async {
print("ViewCamerasMap - _buildCamerasGeoPoint - Adding geopoint camera: ${camera.label}");
try {
final geoPoint = GeoPoint(
latitude: double.parse(camera.latitude!),
longitude: double.parse(camera.longitude!),
);
await controller.addMarker(
geoPoint,
markerIcon: MarkerIcon(assetMarker: AssetMarker(image: camera.iconPath())));
} catch(e) {
print("ViewCamerasMap - _buildCamerasGeoPoint - Error = $e");
}
});
}
@override
Future
@override void dispose() { controller.dispose(); super.dispose(); }
}
class CustomController extends MapController { CustomController({ bool initMapWithUserPosition = true, GeoPoint? initPosition, BoundingBox? areaLimit = const BoundingBox.world(), }) : assert( initMapWithUserPosition || initPosition != null, ), super( initMapWithUserPosition: initMapWithUserPosition, initPosition: initPosition, areaLimit: areaLimit, );
@override void init() { super.init(); }
}
in android osmdroid already use cache to show tile for ios and web the sdk use others ways to show tiles the issue if you init map with user position it takes time to get the information and show the map because we wait until we get the information to show the map we will try to improve the proccess maybe init the map at 0,0 and later move the map to user position
I made your recommended fix (map init at 0,0) but it doesn't change anything to the display time, it is still very slow. Any other suggestion ? Cheers.
Having to wait once for the map to load is acceptable. Is it possible to load it only once when the app is initialising ?
its depend if in your app the map is not the main widget so everytime you open page ot part to show the map it will reload