简体   繁体   English

Xamarin.Forms 中的对象处理

[英]Object disposing in Xamarin.Forms

I'm looking for the right way to dispose objects in a Xamarin Forms application.我正在寻找在 Xamarin Forms 应用程序中处理对象的正确方法。 Currently i'm using XAML and MVVM coding style.目前我正在使用 XAML 和 MVVM 编码风格。 Then from my view model i get a reference to a disposable object through the builtin service locator ( DependencyService ).然后从我的视图模型中,我通过内置服务定位器( DependencyService )获得对一次性对象的引用。 Ideally i should be able to call Dispose() on the objects from my view model, but other solutions like attaching to ContentPage.OnDisappearing and NavigationPage.Popped could be feasible.理想情况下,我应该能够从我的视图模型中对对象调用 Dispose(),但其他解决方案,如附加到ContentPage.OnDisappearingNavigationPage.Popped可能是可行的。

I had pretty much the same requirement a couple of weeks ago.几周前我有几乎相同的要求。 I wanted to make sure that event subscriptions in my view models would be unsubscribed when the page is closed.我想确保当页面关闭时,我的视图模型中的事件订阅将被取消订阅。 After a lot of research my conclusion was that the simplest solution was to use the ContentPage.OnDisappearing method.经过大量研究,我的结论是最简单的解决方案是使用 ContentPage.OnDisappearing 方法。

As you pointed out the object you want to dispose is in your ViewModel, so you need a little bit of infrastructure to make sure your ViewModel is informed when the it's disappearing.正如您指出要处理的对象在您的 ViewModel 中,因此您需要一些基础设施来确保您的 ViewModel 在它消失时得到通知。 To do that I defined a base implementation of my view model that had two key methods OnAppearing and OnDisappearing (note this was a class rather than an interface because I have other base functionality such as IPropertyNotify implementation - not shown here).为此,我定义了视图模型的基本实现,它有两个关键方法 OnAppearing 和 OnDisappearing(注意这是一个类而不是接口,因为我有其他基本功能,例如 IPropertyNotify 实现 - 此处未显示)。

public class ViewModelBase
{
    /// <summary>
    /// Called when page is appearing.
    /// </summary>
    public virtual void OnAppearing()
    {
        // No default implementation. 
    }

    /// <summary>
    /// Called when the view model is disappearing. View Model clean-up should be performed here.
    /// </summary>
    public virtual void OnDisappearing()
    {
        // No default implementation. 
    }
}

Then I subsclassed ContentPage and override the OnAppearing and OnDisappearing methods and then use them to notify my view model.然后我将 ContentPage 子类化并覆盖 OnAppearing 和 OnDisappearing 方法,然后使用它们来通知我的视图模型。

public class PageBase : ContentPage
{
    /// <summary>
    /// Performs page clean-up.
    /// </summary>
    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        var viewModel = BindingContext as ViewModelBase;

        // Inform the view model that it is disappearing so that it can remove event handlers
        // and perform any other clean-up required..
        viewModel?.OnDisappearing();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        // Inform the view model that it is appearing
        var viewModel = BindingContext as ViewModelBase;

        // Inform the view model that it is appearing.
        viewModel?.OnAppearing();
    }
}

Then when you implement a page just make sure that it is of type PageBase:然后当你实现一个页面时,只需确保它是 PageBase 类型:

<?xml version="1.0" encoding="utf-8" ?>
<pages:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          xmlns:controls="clr-namespace:Forms.App.Controls;assembly=Forms.App"
          xmlns:converters="clr-namespace:Forms.App.Converters;assembly=Forms.App"
          xmlns:pages="clr-namespace:Forms.App.Pages;assembly=Forms.App"
          x:Class="Forms.App.Pages.LogonPage"
          NavigationPage.HasNavigationBar="False"
          Title="Logon">

And in your ViewModel you can then override your OnDisappearing method and dispose your objects:然后在您的 ViewModel 中,您可以覆盖 OnDisappearing 方法并处理您的对象:

public class FormViewModel : ViewModelBase
{
    public override void OnDisappearing()
    {
        base.OnDisappearing();

        // Dispose whatever objects are neede here
    }
}

Just one thing to watch out for - if you're using stack navigation the OnDisappearing method gets called when you stack another page on-top of your current page (your page is disappearing temporarily after all).需要注意的一件事 - 如果您使用堆栈导航,当您在当前页面的顶部堆叠另一个页面时会调用 OnDisappearing 方法(毕竟您的页面暂时消失了)。 So you will need to cater for this and probably not dispose your object in that case.因此,您将需要满足这一点,并且在这种情况下可能不会处理您的对象。 However if you're not stacking anything on-top of your page there is nothing to worry about.但是,如果您没有在页面顶部堆叠任何内容,则无需担心。 In my case it was just event subscriptions so I attached the event handlers in the OnAppearing and detached them on the OnDisappearing.就我而言,它只是事件订阅,所以我在 OnAppearing 中附加了事件处理程序,并在 OnDisappearing 上分离了它们。

I hope that helps you out!我希望能帮到你!

We were getting disposed of object exceptions in Forms when Bindings to ListViews or Labels changed values as pages/fragments were being disposed of.当绑定到 ListViews 或 Labels 更改值时,我们在 Forms 中处理了对象异常,因为页面/片段被处理。 I'm assuming you could dispose of objects in your ViewModel the same place we were removing bindings.我假设您可以在我们删除绑定的同一位置处理 ViewModel 中的对象。

protected override void OnParentSet()
{
    base.OnParentSet();

    if (Parent == null)
    {
        //Clear a bunch of bindings or dispose of ViewModel objects 
        BindingContext =
            _listView.ItemsSource = null;
    }
}

I have View Models that conform to IDisposable.我有符合 IDisposable 的视图模型。 So I needed a way for the Page's BindingContext to be disposed when the page is no longer needed.因此,当不再需要页面时,我需要一种方法来处理页面的 BindingContext。

I used the suggestion of Nick which uses OnParentSet being set to NULL to known when the page is no longer needed.我使用了 Nick 的建议,它使用 OnParentSet 设置为 NULL 以知道何时不再需要页面。

The SafeContentPage class can be used in place of ContentPage. SafeContentPage 类可用于代替 ContentPage。 Iff The binding context supports IDisposable will it automatically try to dispose the binding context.如果绑定上下文支持 IDisposable,它会自动尝试处理绑定上下文。

public class SafeContentPage : ContentPage
{
    protected override void OnParentSet()
    {
        base.OnParentSet();
        if (Parent == null)
            DisposeBindingContext();
    }

    protected void DisposeBindingContext()
    {
        if (BindingContext is IDisposable disposableBindingContext) {
            disposableBindingContext.Dispose();
            BindingContext = null;
        }
    }

    ~SafeContentPage()
    {
        DisposeBindingContext();
    }
}

The OnDisappearing method isn't a reliable technique as there are platform differences in terms of when it is called, and just because the page disappeared doesn't mean its View Model is no longer needed. OnDisappearing 方法不是一种可靠的技术,因为在调用它的时间方面存在平台差异,并且仅仅因为页面消失并不意味着不再需要它的视图模型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM