Search code examples
c#xamarindelegatesxamarin.formsdelegation

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.


Solution

  • 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