android - MvvmCross Android - ViewModel 从未被垃圾收集

标签 android xamarin mvvmcross

我注意到由于同一 ViewModel 的多个实例,MvxMessenger 订阅被多次调用。我阅读了一些关于取消订阅和处理 token 的内容(这有效并防止多次调用),但我希望看到 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 绑定(bind)到这些 ViewModel。如果我转到 SecondViewModel 并单击发送,我会看到订阅的事件触发一次。如果我在 First 和 SecondViewModel 之间来回切换,这些事件订阅会建立起来,单击“发送”会触发它们中的每一个。单击 GarbageCollect 似乎没有任何区别(我希望看到它在单击后仅被调用一次)。

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

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

这可能与最近对 Xamarin.Android 的更改有关吗?还是有什么我不明白的!

非常感谢

最佳答案

我知道现在回答为时已晚,但为了引用:

简答:

在 View (MvxActivity)中,像这样处理 DestroyCalled 事件:

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

在 View 模型中,实现 IDisposable 接口(interface):

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

关于android - MvvmCross Android - ViewModel 从未被垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30798429/

相关文章:

android - 如何在错误情况下非阻塞地组合多个 RxJava 链

Xamarin Forms Android 应用程序在启动后崩溃(启动)

Xamarin.Forms 如何在设备上打开默认电子邮件客户端?

ios - 尝试创建每个工作日重复的 UILocalNotification

xamarin.android - 将多个目标绑定(bind)到同一源

c# - 'DateTime' 不包含 'FromOADate' 的定义

java - 如何从android中的另一个方法调用线程内的run方法?

android - 如何使用 Kotlin async 并等待阶乘?

在模拟器中没有看到 Android 日历应用程序。

c# - MvvmCross Windows Store 如何将不同的 ViewModel 绑定(bind)到 Appbar?