MvvmCross Android - ViewModel从不垃圾收集

时间:2015-06-12 08:16:33

标签: android xamarin mvvmcross

我注意到由于同一ViewModel的多个实例,多次调用了MvxMessenger订阅。我读了一些关于取消订阅和处理令牌(它可以工作并阻止多次调用)的内容,但我希望看到ViewModel自然地被垃圾收集,并且看到了Messenger订阅。

我想为Android设置类似于此https://github.com/slodge/MessengerHacking的测试项目。所以这是两个ViewModels

public class FirstViewModel : MvxViewModel
{
    private string _hello = "Hello MvvmCross";
    public string Hello
    { 
        get { return _hello; }
        set { _hello = value; RaisePropertyChanged(() => Hello); }
    }

    private MvxCommand _showSecond;
    public ICommand ShowSecond {
        get {
            _showSecond = _showSecond ?? new MvxCommand(() => ShowViewModel<SecondViewModel> ());
            return _showSecond;
        }
    }
}

public class SecondViewModel : MvxViewModel
{
    private readonly IMvxMessenger _messenger;
    private readonly MvxSubscriptionToken _token;

    public SecondViewModel(IMvxMessenger messenger) {
        _messenger = messenger;
        _token = _messenger.Subscribe<MyMessage> ((message) => {
            Debug.WriteLine("incoming message");
        });
    }

    private MvxCommand _send;
    public ICommand Send {
        get {
            _send = _send ?? new MvxCommand(() => _messenger.Publish (new MyMessage (this)));
            return _send;
        }
    }

    private MvxCommand _garbageCollect;
    public ICommand GarbageCollect {
        get {
            _garbageCollect = _garbageCollect ?? new MvxCommand(() => GC.Collect ());
            return _garbageCollect;
        }
    }
}

然后我只有两个MvxActivities绑定到这些ViewModels。如果我转到SecondViewModel并单击发送,我会看到订阅的事件触发一次。如果我在First和SecondViewModel之间来回切换,则会生成这些事件订阅,然后单击Send会触发每个订阅。单击GarbageCollect似乎没有任何区别(我希望看到它在单击此项后仅调用一次)。

感觉好像当我从SecondViewModel点击后退按钮时,一旦MvxActivity被销毁,那么SecondViewModel应该有资格进行垃圾收集。

我注意到的另一件事是,即使我订阅而不将其保存到令牌中,行为也是一样的。我成功获取事件以停止触发的唯一方法是保存令牌并在令牌上调用Unsubscribe或Dispose,但感觉在这种情况下SecondViewModel仍然没有收集垃圾。

这可能与最近对Xamarin.Android的更改有关吗?或者有些东西我还没有得到!

非常感谢

1 个答案:

答案 0 :(得分:1)

我知道答案为时已晚,但为了参考:

简答:

在视图(MvxActivity)中,处理DestroyCalled事件,如下所示:

DestroyCalled += (s, e) =>
{
    if (ViewModel is IDisposable)
        (ViewModel as IDisposable).Dispose();
};

在viewmodel中,实现IDisposable接口:

public new void Dispose()
{
    base.Dispose();
    //Unsubscribe messages here
}

长答案:

http://slodge.blogspot.co.uk/2013/11/n42-is-my-viewmodel-visible-can-i-kill.html