How to handle long delay in displaying map with large poly line

plugins

#1

This is with the nativescript-google-maps-sdk plugin. Yes, this is a cross-post from an issue I opened on that plugin’s GitHub site, but I’m hoping for more attention than I might get there…

I create maps with a few markers and a large polyline that shows a route. All this works fine, except it can take 10-12 seconds for the map to load. I haven’t found a way to display an activity indicator, as the blank map fills the screen. This makes it look like the app is hung. Thus, is there any way I can,

  1. Speed up the performance? I believe the issue is the thousands of calls to polyline.addPoints
  2. Show the map elements as they’re created? For example, map markers one at a time, then the one or two poly lines I have.
  3. Show an activity indicator?

I’d really appreciate any help on this, as I’m about searched out.


#2

I’m not sure how the performance could be improved as we don’t see any sample project that demonstrate the issue. When I tried drawing routes last time it was faster, at least not more than 10 seconds until the network was really slow.

But you can add an activity indicator that blocks the UI while it loads. Try this,


#3

@manojdcoder - thanks for your response! I appreciate all your input.

I want to see if I can “pre-compile” the polyline by creating it and then saving the object in JSON format. Then I’ll try to simply load the JSON rather than re-create the polyline each time. It may be a few days before I can get back to that. This, coupled with the activity indicator (thanks for that, too), I hope will get the job done.


#4

Here’s an update, for anyone who might be interested. After working on this for two days I’ve finally made some progress, at least with an activity indicator. Here’s the code in question:

 datafile.readText()
   .then(function (content) {
      var latlngs = content.split("\n");  // separate .coo file into lat,lng lines
      latlngs.pop();  // remove empty last line 
      let polyline = new mapsModule.Polyline();
      let plpoint = [];
      let start = Date.now();
      latlngs.forEach((latlng) => {
        plpoint = latlng.split(",");  // separate lat,lng 
        polyline.addPoints([mapsModule.Position.positionFromLatLng(plpoint[0], plpoint[1])]);
      });
      console.log("points added @ " + (Date.now() - start));
      polyline.visible = true;
      polyline.width = (androidApp ? 14 : 4);  // 14 for Android, 4 for iOS
      polyline.color = segment.color;
      polyline.geodesic = true;
      mapView.addPolyline(polyline);
      viewModel.set("isBusy", false); // dismiss activity indicator
    }, function (error) { // (readText failed)
      console.log(error); //TODO: better debugging here?
    });

The forEach loop in the middle is the culprit. My 3700+ points can take over 8 seconds to load on an iPhone 6s. Creating and consuming a JSON object didn’t work. Here’s a snippet of that code:

let jsonfile = filesFolder.getFile(key + ".json.txt"); 
let polylineObj = JSON.parse(jsonfile.readTextSync());
var newpolyline = Object.assign(new mapsModule.Polyline(), polylineObj);
mapView.addPolyline(newpolyline);

Object.assign doesn’t fully recreate the polyline object, nor the thousands of Position objects. I’d also need separate JSON files for iOS and Android.

I have, however, had some success with an activity indicator. This code snippet seems to work nicely:

<GridLayout >
  <Label class="loading" visibility="{{ isBusy ? 'visible' : 'collapsed' }}" textWrap="true" 
  text="Map will load in a few moments..."/>
  <ActivityIndicator height="80" width="80" busy="{{ isBusy }}" visibility="{{ isBusy ? 'visible' : 'collapsed' }}" />
  <maps:mapView id="locmap" latitude="{{ latitude }}" longitude="{{ longitude }}" zoom="{{ zoom }}" 
    visibility="{{ isBusy ? 'collapsed' : 'visible' }}"
    mapReady="onMapReady" markerSelect="onMarkerSelect"  markerInfoWindowTapped="onMarkerInfoWindowTapped">
...

So, I can at least let the user know the app is not hung, but I’d still like a way too make this faster.


#5

So, I spoke too soon. The StackLayout with the activity indicator works just fine on iOS, but isn’t visible at all on Android. Getting ready for more head-banging (not the rock 'n roll kind).


#6

So, after playing with this for a while, I have corrected the error by moving the addPoints call outside of the loop.

      // Convert each latlngs[] entry to Position object
      latlngs.forEach((latlng, i) => {
          plpoint = latlng.split(",");  // separate lat,lng 
          latlngs[i] = mapsModule.Position.positionFromLatLng(plpoint[0], plpoint[1]);
        });
        polyline.addPoints(latlngs);

This improved the performance from 9 seconds to .03 seconds, thus eliminating the need for an activity indicator.