mapsplugin / cordova-plugin-googlemaps

Google Maps plugin for Cordova
Apache License 2.0
1.66k stars 918 forks source link

[Android] Polyline no longer clickable after changing it's points #2893

Open ebhsgit opened 3 years ago

ebhsgit commented 3 years ago

I'm submitting a ... (check one with "x")

OS: (check one with "x")

cordova information: (run $> cordova plugin list)

cordova-androidx-build 1.0.4 "cordova-androidx-build"
cordova-plugin-device 2.0.3 "Device"
cordova-plugin-googlemaps 2.8.0-20200709-2008 "cordova-plugin-googlemaps"
cordova-plugin-ionic-keyboard 2.2.0 "cordova-plugin-ionic-keyboard"
cordova-plugin-ionic-webview 4.1.1 "cordova-plugin-ionic-webview"
cordova-plugin-splashscreen 5.0.3 "Splashscreen"
cordova-plugin-statusbar 2.4.3 "StatusBar"
cordova-plugin-whitelist 1.3.4 "Whitelist"

If you use @ionic-native/google-maps, please tell the package.json (only @ionic-native/core and @ionic-native/google-maps are fine mostly)

@ionic-native/core : 4.20.0
@ionic-native/google-maps : 4.21.0

Current behavior:

When a map has multiple polylines, and the code changes the points of a polyline (eg: polyline.setPoints() or directly modify the polyline points array).

Expected behavior:

All polylines should still register the click event

Screen capture or video record:

Related code, data or error log (please format your code or data):

Project that demo this issue

https://github.com/ebhsgit/gmap-test/tree/bug-multi_polyline_incorrect_bounds

Steps

  1. Click Create Polylines
  2. Click on Yellow polyline (and any other polyline) to show a marker at point of click. See that all the polylines register click
  3. Click Change points on green
  4. Click on Yellow polyline. Notice that it no longer registers any click

NOTE: Green line is still registering the click because the new points are within the original bounds If you change the code as below, then green polyline will no longer register click event as well.

    changePoints_green() {
        const newPoints = this.greenPolyline.getPoints().map(p => {
            return {
                lat: p.lat * -1,
                lng: p.lng,
            } as ILatLng
        })

        this.greenPolyline.setPoints(newPoints)
    }

Cause:

PluginPolyline.create is called for each polyline, with it's unique hashCode (polylineHashCode) Only one instance of PluginPolyline is registered in PluginManager, with the same service id map-{{mapId}}-polyline When a polyline function is called in javascript, it invokes the cordova plugin with id map-{{mapId}}-polyline.

If the program ever makes any changes to a polyline, the object cache in Java side of the program will become out of sync. Because all of the functions in PluginPolyline make use of the instance's polylineHashCode to construct the cache property ids. Since every polyline is created with the same instance of the plugin, the polylineHashCode is overwritten every time. So it will always be the hashCode of the last polyline.

Fix suggestions

There are many potential fixes for this issue. It will come down to the preferred solution architecture

  1. Keep many instance of the Plugin

Register each instance of the plugin to PluginManager. Add the hashcode to the service id. ie: map-{{id}}-polyline-{{hashcode}}. Change javascript to invoke the cordova plugin by adding the hashcode

  1. Only one instance of Plugin

Create only one instance of each type of Plugin. Does not need to change any of the javascript code

The caller already pass the id argument. Which is {{type}}_{{hashcode}}, eg: polyline_{{hashcode}}. So each function can extract the hashcode from theid` argument

  1. Javascript pass the hashCode instead of the id

Instead of passing the id argument ({{type}}_{{hashcode}}), the caller should pass the hashCode Then the id and other property keys can be constructed in the Plugin

NOTE

This bug has bigger impact than the described symptoms. All map Plugins are implemented this way. Which means any change which requires "object cache syncing" will be impacted.

For example, I believe Polygons are also impacted.

Support this plugin activity

I appreicate if you give me a beer :beer: from here