【问题标题】:Avoiding Memory Leak. (WeakReference)避免内存泄漏。 (弱参考)
【发布时间】:2017-01-23 05:45:22
【问题描述】:

这是场景:

带有条目的 XAML 有一个链接到 textchanged 事件的方法。

在将 UI 组件(本例中为网格)封装在类中以提高代码的可维护性后,我发现了下一个问题:

我无法将方法的事件链接到网格上的特定按钮。问题是我正在调用这个方法(它有一个不能在简单类中调用的 DisplayActionSheet 函数。它应该来自任何类型的 Page 类或 Application 类)。

所以我的第一个方法是将按钮封装在另一个类中。 我在页面中创建了这个对象(按钮),链接到方法的事件(也在页面中编码。现在我可以,在页面的类中)并将这个对象传递给网格对象构造函数的新实例(另一堂课)。最后,我将网格(带有正确链接到其中的按钮)添加到页面。

好吧,我担心这不是一个好主意。我假设这可能源于“内存泄漏问题”(与删除内存中的对象相关的问题,并且这些对象在组成它们的不同类之间有引用,不是吗?),只是在不同的类(网格、按钮和页面)。

在研究解决方案后,似乎要委托此方法的事件。

但我无法实现它,这很容易(当你知道的时候),但这些例子不是我的案例准备的(或者我找不到它)。你能帮忙吗? :)

我发布了代码的想法,它是通过 ListView 内部的 Button 实现的,在网格内部(有点复杂,但我想简化它)。

            //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...
        }

谢谢大家。

【问题讨论】:

    标签: c# xamarin delegates xamarin.forms delegation


    【解决方案1】:

    所有移动平台(ios、android、xamarin)都使用弱引用来存储(页面、活动、UIViewcontroller)是一种很好的做法。您可以像这样实现对页面的引用:

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

    并且不要忘记在访问页面属性时检查是否为空。这样你就不会发生内存泄漏。要了解有关弱引用的更多信息,请阅读: https://msdn.microsoft.com/en-us/library/gg712738(v=vs.110).aspx

    作为一个好的做法,我建议使用 FreshMvvm 使用 MVVM 方法,将按钮命令绑定到模型,并使用 CurrentPage 参数显示操作表

    【讨论】:

    • 感谢您的回答@Greensy,但它对我有什么帮助?如果我将网格封装在另一个类中(里面有按钮),我仍然不能调用带有 DisplayActionSheet 的方法。对吗?
    • 您可以将页面引用传递给您需要的任何对象,并调用操作表显示而不会发生内存泄漏。您甚至可以对当前页面进行静态引用(这不是一个好主意)。但是您仍然不会出现内存泄漏,并且可以访问页面方法。
    • Bbbuufff,很迷茫。所以,我必须像你的例子一样创建一个类,当我需要 Page 调用 _pageReference 时?我只是在 xaml 中使用它,所以:x:Class="ToFlowClient.NewClass._pageReference"?以及我如何在我的类中调用它:网格(我只需要将按钮链接到其中的特定方法)?顺便说一句,我正在使用 MVVM。
    • 您可以将页面传递给网格视图构造函数。但无论如何,您是否可以使用 gist 访问您的页面代码。所以我可以更详细地解释一下。
    • @GeorgeThomas 是的,没错。但是,如果 Xamarin.Forms 导航在内部使用弱引用,您可能需要强引用。仅供参考,如果您需要存储列表或字典操作系统页面,请使用 Wea​​kHashTable
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 2018-04-08
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多