【问题标题】:MvvmCross Android - ViewModel never garbage collectedMvvmCross Android - ViewModel 从不垃圾收集
【发布时间】:2015-06-12 08:16:32
【问题描述】:

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

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

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 绑定到这些 ViewModel。如果我转到 SecondViewModel 并单击发送,我会看到订阅的事件触发一次。如果我在 FirstViewModel 和 SecondViewModel 之间来回切换,这些事件订阅会建立起来,然后单击 Send 会触发它们中的每一个。点击 GarbageCollect 似乎没有任何区别(我希望在点击后看到它只被调用一次)。

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

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

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

非常感谢

【问题讨论】:

    标签: android xamarin mvvmcross


    【解决方案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

    【讨论】:

    • 谢谢迈赫迪!这几乎就是我最终做的事情,它解决了信使问题。虽然我仍然不禁想知道为什么 ViewModel 似乎无法被垃圾收集。感觉就像,导航足够长的时间会构建大量的 ViewModel。也许存在某种特定于 Android 和 MvvmCross 的内存泄漏?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多