EliasMP EliasMP - 6 days ago 6
C# Question

Avoiding Memory Leak. (WeakReference)

This is the scenario:

A XAML with a Entry has a method linked to textchanged´s event.

After encapsulate the UI component(grid in this case) in classes for improving the mantenibility of the code I found the next issue:

I can´t link the method´s event to a specific button on the grid. The problem is I´m calling this method (which has a DisplayActionSheet function which Can´t be call in a simple class. It should be coming from any kind of Page´s class or Application class).

So my first approach was to encapsulate the button in another class.
I created this object(button) in the Page, linked to the method´s event (coded in the page as well. Now I can, is in Page´s class) and pass this object to a new instance of the grid object constructor(another class). Finally I added the grid(with button properly linked into it) to the Page.

Well, I fear this is not really good idea. I am supposing this could be derive in a "Memory Leak Issue" (problem related about deleting object in memory and those have references between different classes what compose them, isn´t?), just creating references between different classes (grid, button and page).

After researching the solution looks like to delegate this method´s event.

But I can´t achieve it, It´s easy (when you know) but the examples are not prepare by my case (or I can´t find it). Could you give a hand? :)

I post the idea of the code, It was implemented over Button inside of a ListView, inside of a grid(a bit more complex, but I want to simplify it).

//This code is called in CarouselPage
// ..............
//ButtonEstadoTarea is type Button
ButtonEstadoTarea bet = new ButtonEstadoTarea();
//OnStartClicked is allocated is this CarouselPage
//
bet.Clicked += this.OnStartClicked;

ListViewIntervencion lvi = new ListViewIntervencion();
lvi.ItemTapped += this.OnItemTapped;
lvi.ItemsSource = intervencion.Interv;

GridCabeceraIntervencion gci = new GridCabeceraIntervencion(intervencion, lvi);
var intervencionContent = new ContentPage
{
Content = gci,
};

this.Children.Add(intervencionContent);

async void OnStartClicked(object sender, EventArgs args)
{
var action = await DisplayActionSheet("Procesar Tarea", null, "Cancel", "Iniciar", "Pausar", "Bloquear", "Terminar");
// MORE MAGIC...
}


Thanks guys.

Answer

It is good practice for all mobile platforms(ios, android, xamarin) to use weak reference for storing (page, activity, UIViewcontroller). You can implements reference to page like this:

WeakReference<Page> _pageReference;
public Page Page{
   get {
      Page _page = null;
      _pageReference.TryGetTarget(out _page);
      return _page;
   }
   set{
      _pageReference = new WeakReference<Page>(value);
   }
}

And do not forget ot check for null, when accessing page property. This way you will not have memory leak. To find out more about weak references, please read: https://msdn.microsoft.com/en-us/library/gg712738(v=vs.110).aspx

As a good practice i suggest to use MVVM approach using FreshMvvm, bind button command to model, and display action sheet using CurrentPage parameter

Comments