I am trying to create a MapBox Renderer for Android in Xamarin Forms using the naxam library. The map is displaying well as a content of a view in a tab, however when I change tab several times it crashes on the android emulator. I suppose the problem comes from the renderer but can't figure out where.
Here is a part of my code :
public class MapViewRenderer : ViewRenderer<ContentView, Android.Views.View>,
IOnMapReadyCallback, Com.Mapbox.Mapboxsdk.Maps.Style.IOnStyleLoaded
{
private MapView _mapView = null;
private MapboxMap _mapBox = null;
public MapViewRenderer(Context context) : base(context)
{
Mapbox.GetInstance(Context, "pk.###");
}
public void OnMapReady(MapboxMap p0)
{
_mapBox = p0;
[...]
}
public void OnStyleLoaded(Com.Mapbox.Mapboxsdk.Maps.Style p0)
{
[...]
}
protected override void OnElementChanged(ElementChangedEventArgs<ContentView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_mapView = new MapView(Context);
_mapView.GetMapAsync(this);
view.Content = _mapView.ToView();
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_mapView.Dispose();
}
base.Dispose(disposing);
}
}
All the examples I read on the net are about creating the MapView in the main activity with OnCreate, OnStart, OnResume... I haven't found any about creating a map in a custom render.
Please help.
EDIT :
---------------------------------SOLUTION---------------------------------
The problem was fixed using the code below in the custom renderer. In addition the renderer uses a Mapview instance which has been moved inside the main activity following ToolmakerSteve's remark.
MapViewRenderer.cs :
public class MapViewRenderer : ViewRenderer<ContentView, Android.Views.View>
{
public MapViewRenderer(Context context) : base(context)
{}
protected override void OnElementChanged(ElementChangedEventArgs<ContentView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var view = e.NewElement as Views.Map;
if (Control == null)
{
SetNativeControl(MainActivity.MainActivityInstance.MapView);
}
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
MainActivity.MainActivityInstance.MapView.RemoveFromParent();
}
base.Dispose(disposing);
}
}
MainActivity.cs :
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IOnMapReadyCallback, Style.IOnStyleLoaded
{
public MapView MapView { get; private set; } = null;
public MapboxMap MapboxMap { get; private set; } = null;
public static MainActivity MainActivityInstance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
[...]
MainActivityInstance = this;
Mapbox.GetInstance(this, "pk.###");
MapView = new MapView(this);
MapView.GetMapAsync(this);
MapView.OnCreate(savedInstanceState);
}
protected override void OnStart()
{
base.OnStart();
MapView.OnStart();
[...]
}
protected override void OnResume()
{
base.OnResume();
MapView.OnResume();
}
protected override void OnPause()
{
MapView.OnPause();
base.OnPause();
}
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
MapView.OnSaveInstanceState(outState);
}
protected override void OnStop()
{
base.OnStop();
MapView.OnStop();
}
protected override void OnDestroy()
{
MapView.OnDestroy();
base.OnDestroy();
}
public override void OnLowMemory()
{
base.OnLowMemory();
MapView.OnLowMemory();
}
public void OnMapReady(MapboxMap p0)
{
MapboxMap = p0;
[...]
}
public void OnStyleLoaded(Com.Mapbox.Mapboxsdk.Maps.Style p0)
{
[...]
}
}