0

正如之前在一些 MvvmCross 视频中详述的那样 ( http://www.youtube.com/watch?v=cYu_9rcAJU4&feature=youtu.be&t=33m41s )

我正在尝试从我的视图模型中删除对我的视图的强引用。

在使用了 PropertyChanged += 的地方实现了 WeakSubscribe(),我现在遇到了一些使用 Action 来允许视图观察的场景。我认为这将再次导致潜在的内存泄漏,因此试图根除。

但是 - WeakReference 的工作原理是挂钩到 INotifyPropertyChanged 源:

https://github.com/MvvmCross/MvvmCross/blob/162a816d148df224df0b8f635aeafe30c0910de9/CrossCore/Cirrious.CrossCore/WeakSubscription/MvxWeakSubscriptionExtensionMethods.cs

那么我是否应该重构我的代码以放弃 Action 并通过 PropertyChanged 触发以便能够通过弱引用通知视图?

这是一些示例代码,仅供参考 - 当前强引用的架构。

视图模型

    public event Action Loaded;
    public HomeViewModel()
    {
        FeaturedProductCategoryViewModel = new FeaturedProductsViewModel();
        FeaturedProductCategoryViewModel.OnPopulated += () =>
        {
            if (Loaded != null) Loaded();
        };
    }

看法

    public MainHomePageView()
        : base(GetNibName("MainHomePageView"), null)
    {
        this.EnableLandscapeRotation ();
    }

    protected override void ViewJustLoaded()
    {
        this.ViewModel.Loaded += LoadControls;
    }

    void LoadControls()
    {
        //load controls when view model is populated
    }
4

2 回答 2

1

MvvmCross 的弱引用方法背后的驱动心态是 ViewModel 永远不应该引用 Views - 好像他们这样做那样会导致 Views 引用其包含的 Views。

这方面的一些背景在https://stackoverflow.com/a/14734264/373321

对于像Loaded它有点非正统Action类型的事件,我认为可以使用新的WeakSubscribe扩展方法和处理程序来订阅它。

或者,您可以更改Loaded为一种EventHandler类型,然后使用WeakSubscribe(this EventInfo eventInfo, ...扩展方法:

  // ViewModel - define event
  public event EventHandler Loaded;

  // View - subscription
  IDisposable _subscription;

  // View - in ViewDidLoad
  _subscription = typeof(HomeViewModel)
                      .GetEvent("Loaded")
                      .WeakSubscribe(this.ViewModel, OnLoaded);

  // View - event handler
  public void OnLoaded(object sender, EventArgs e)
  {
     LoadControls();
  }
于 2013-10-15T11:17:47.267 回答
0

我认为更好的解决方案是在视图模型中有一个布尔属性(称为 IsBusy),然后,当您开始加载时 - 将 IsBusy 设置为 true。完成加载后 - 将其设置回 false;然后在您的视图中,使用 mvvmcross 属性侦听器对加载完成进行操作

        listener = new MvxPropertyChangedListener(IncidentViewModel).Listen<bool>(
            () => IncidentViewModel.IsBusy,
            () =>
            {
                if (IncidentViewModel != null && !IncidentViewModel.IsBusy)
                {
                    LoadControls();
                }
            });
于 2015-10-20T10:47:30.273 回答