使用Action <t> </t>在MvvmCross中引用弱引用

时间:2013-10-15 10:08:27

标签: c# xamarin.ios mvvmcross

如前所述,某些MvvmCross视频(http://www.youtube.com/watch?v=cYu_9rcAJU4&feature=youtu.be&t=33m41s

我正在尝试从我的viewmodel中移除强引用到我的视图。

实现了WeakSubscribe(),其中使用了PropertyChanged + =我现在遇到了一些使用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
    }

2 个答案:

答案 0 :(得分:1)

MvvmCross弱引用方法背后的驱动思路是ViewModels永远不应该引用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();
  }

答案 1 :(得分:0)

我认为更好的解决方案是在视图模型中使用bool属性(称为IsBusy),然后在开始加载时将IsBusy设置为true。完成加载后 - 将其设置为false;然后在您的视图中,使用mvvmcross属性侦听器来执行加载完成

        listener = new MvxPropertyChangedListener(IncidentViewModel).Listen<bool>(
            () => IncidentViewModel.IsBusy,
            () =>
            {
                if (IncidentViewModel != null && !IncidentViewModel.IsBusy)
                {
                    LoadControls();
                }
            });