osm_flutter icon indicating copy to clipboard operation
osm_flutter copied to clipboard

Slow display of the map

Open Alisofin opened this issue 2 years ago • 4 comments

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 zoomNotifierActivation = ValueNotifier(false); ValueNotifier visibilityZoomNotifierActivation = ValueNotifier(false); ValueNotifier advPickerNotifierActivation = ValueNotifier(false); ValueNotifier trackingNotifier = ValueNotifier(false); ValueNotifier showFab = ValueNotifier(true); ValueNotifier<GeoPoint?> lastGeoPoint = ValueNotifier(null); Timer? timer; int x = 0;

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 _getSharedCamerasList() async { _sharedCameras = await Provider.of<PhotoService>(context, listen: false).getSharedCameras(); print("ViewCamerasMap - _getSharedCamerasList - sharedCamerasList = ${_sharedCameras}"); print("ViewCameraMap - _getSharedCamerasList - end - ${stopwatch.elapsedMilliseconds}");

}

/// ********************************************************************** /// 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 mapIsReady(bool isReady) async { if (isReady) { print("ViewCamerasMap - mapIsReady"); _mapIsReady = true; await mapIsInitialized(); } }

Future mapIsInitialized() async { print("ViewCameraMap - mapIsInitialized - start - ${stopwatch.elapsedMilliseconds}");

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 _buildCamerasGeoPoint() async {

// 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 mapRestored() async { super.mapRestored(); print("mapRestored"); print("log map restored"); }

@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(); }

}

Alisofin avatar Jul 01 '23 13:07 Alisofin

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

liodali avatar Jul 02 '23 18:07 liodali

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.

Alisofin avatar Jul 03 '23 06:07 Alisofin

Having to wait once for the map to load is acceptable. Is it possible to load it only once when the app is initialising ?

Alisofin avatar Jul 09 '23 14:07 Alisofin

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

liodali avatar Jul 09 '23 14:07 liodali