OnMapReady is called twice in a Forms.Map custom renderer on Android (occurs in version 2.4.0.18342)

JosHuybrighsJosHuybrighs USMember ✭✭
edited October 31 in Xamarin.Forms

After updating xamarin forms to 2.4.0.18342 (before I was using 2.3.4.231) I am experiencing that the OnMapReady method is being called twice.
In order to be sure that there wasn't something wrong in my code, I created a fresh forms project (straight from VS) with just a button to open a 'map' page with a custom Map renderer. It shows the same problem.

This is the custom Map renderer:

assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace App4.Droid
{
    class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
    {
        CustomMap _customMap;

        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
            }

            if (e.OldElement != null)
            {
                UnLoad();
            }

            if (e.NewElement != null)
            {
                _customMap = e.NewElement as CustomMap;
                ((MapView)Control).GetMapAsync(this);
            }
        }

        protected override void OnMapReady(GoogleMap map)
        {
            base.OnMapReady(map);
            Load();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                UnLoad();
            }
            base.Dispose(disposing);
        }


        void Load()
        {
            // Register for click events on elements
            this.NativeMap.InfoWindowClick += OnNativeMapInfoWindowClick;
            this.NativeMap.MyLocationChange += OnNativeMapMyLocationChange;
            this.NativeMap.SetInfoWindowAdapter(this);
        }

        void UnLoad()
        {
            // Unsubscribe
            if (this.NativeMap != null)
            {
                // Clear the native map
                this.NativeMap.Clear();

                // Unsubscribe
                this.NativeMap.MyLocationChange -= OnNativeMapMyLocationChange;
                this.NativeMap.InfoWindowClick -= OnNativeMapInfoWindowClick;
            }
        }

        private void OnNativeMapInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs ev)
        {
        }

        private void OnNativeMapMyLocationChange(object sender, GoogleMap.MyLocationChangeEventArgs e)
        {
        }

        public Android.Views.View GetInfoContents(Marker marker)
        {
            throw new System.NotImplementedException();
        }

        public Android.Views.View GetInfoWindow(Marker marker)
        {
            throw new System.NotImplementedException();
        }
    }
}

Sequence of methods being called when the page opens:

OnElementChanged
OnMapReady (with Google map object keyhandle set to e.g. 43fa259)
OnMapReady (with a different Google map object keyhandle than the first)

Since OnMapReady is the place where you register for events on both the native google map and a viewmodel (if you have that) a double registration will lead to serious problems and memory leaks.
I tried to overcome this by only registering the first time OnMapReady is called and that seems to work. Still , this leaves me puzzled why the 2nd call is there, especially since the google map object has a different handle than the first one.

Answers

  • NMackayNMackay GBInsider, University ✭✭✭✭✭

    @JosHuybrighs

    I've noticed the same thing, it's been like this since Forms 2.3.5-pre x, I used a boolean and was just adding a comment when I saw this post,.

     protected override void OnMapReady(GoogleMap googleMap)
            {
                // OnMapReady is called twice, not entirely certain why
                if (_mapDrawn) return;
    
                base.OnMapReady(googleMap);
    
                base.NativeMap.MarkerClick += HandleMarkerClick;
                base.NativeMap.MyLocationEnabled = _formsMap.IsShowingUser;
    
                foreach (var formsPin in _formsMap.CustomPins)
                {
    

    @DavidBritch Hi David, any idea why OnMapReady calls twice, I tested the Xamarin map CustomRender samples and it fires twice, for example this code executes twice:

    protected override void OnMapReady(Android.Gms.Maps.GoogleMap map)
            {
                base.OnMapReady(map);
    
                var polylineOptions = new PolylineOptions();
                polylineOptions.InvokeColor(0x66FF0000);
    
                foreach (var position in routeCoordinates)
                {
                    polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
                }
    
                NativeMap.AddPolyline(polylineOptions);
            }
    
  • NMackayNMackay GBInsider, University ✭✭✭✭✭
    edited November 8

    @JosHuybrighs

    Hi,

    David has kindly posted a bugzilla for this issue so we can track it.

    https://bugzilla.xamarin.com/show_bug.cgi?id=60565)

Sign In or Register to comment.