【问题标题】:Best way to send an async message to the parent viewmodel before closing?在关闭之前向父视图模型发送异步消息的最佳方式?
【发布时间】:2014-02-03 16:37:06
【问题描述】:

我正在从“父”视图模型打开一个对话框视图模型。当对话框关闭时,我希望父视图模型刷新更新的字段。

INotifyPropertyChange 不可用,因为可以关闭和重新创建 android 活动。起初我认为这不是问题:如果重新创建活动,则刷新视图。所以我尝试用父视图拥有的对象实例打开对话框。但是 mvvmcross 不会让你这样做:viewmodel 构造函数参数必须是可序列化的和简单的类型。这是有道理的,因为这些对象使用的内存可能会在 Activity 被销毁时被释放。

IMvxMessenger 似乎是要走的路。在对话框关闭之前从对话框中发布一条刷新消息。父级订阅此消息并相应地刷新属性。

但 IMvxMessenger.Publish 将发送者对象作为参数。这会导致内存泄漏吗?这会将正在关闭的视图模型保留在内存中吗?这对应用稳定性有危险吗?

【问题讨论】:

  • 我的直觉是你实际上是通过某种服务来保存 - 我会从那里发送消息。
  • 你能解释一下你所说的“打开一个对话框视图模型”是什么意思吗?这是一个真正的对话框(例如一个DialogFragment)还是一个新的Activity?不幸的是,这是一个 Android 应用程序/活动生命周期很重要的领域。
  • 这是一个带有对话框主题的Activity。
  • 我知道对于片段来说是没有问题的。父活动不能被回收。对于消息,存储在消息中的所有对象都保留在内存中,直到消息被传递。这是正确的吗 ?它应该:) 如果是,则没有问题并且问题已得到解答。
  • 否 - 在MvxMessenger 中的消息不会存储以供将来传递。如果您想实现一个缓存特定消息类型的“投递箱服务”,那么您可以自己轻松完成。

标签: xamarin.android mvvmcross


【解决方案1】:

IMvxMessenger 似乎是要走的路。从以下位置发布刷新消息 关闭之前的对话框。父母订阅此消息并 相应地刷新属性。

是的,这就是我要走的路,IMO。

但 IMvxMessenger.Publish 将发送者对象作为参数。将要 这会导致内存泄漏?这是否会保留视图模型,即 关闭,在内存中?这对应用稳定性有危险吗?

我不这么认为,除非您使用从订阅者事件处理程序到消息的发送者引用。例如,假设您的订阅者拥有:

_newProductToken = _messenger.Subscribe<NewProductMessage>( OnNewProductMessage, MvxReference.Strong );

您的消息类如下所示:

class NewProductMessage : MvxMessage
{
    public NewProductMessage( object p_sender, string p_code, string p_description )
       : base(p_sender)
    {
        Code = p_code;
        Description = p_sescription;
    }

    public string Code { get; set; }
    public string Description { get; set; }
}

您的订阅者对消息的事件处理程序如下所示:

private void OnNewProductMessage( NewProductMessage p_Product )
{
   // Obviously this might cause an exception if the sender is removed by the time this line is exec'd
   var myvar = p_Product.sender; 

  // But you could use the other properties of your message class of course...
   ProductCode = p_Product.Code;
   Description = p_Product.Description;
}

因此,这完全取决于 MvxMessage 类如何使用通过base(p_sender) 传递给它的发送者对象。您确实需要检查 Messenger 插件的源代码,我相信您可以在这里找到:

https://github.com/MvvmCross/MvvmCross/tree/3.0.14/Plugins/Cirrious/Messenger/Cirrious.MvvmCross.Plugins.Messenger

HTH, 帕普

【讨论】:

    【解决方案2】:

    您可以尝试使用将在调用者中调用的操作。

    public class DialogMessage
        : MvxMessage
    {
        public DialogMessage(object sender) : base(sender)
        {
        }
    
        public string Title { get; set; }
        public string Message { get; set; }
    
        public Style Buttons { get; set; }
    
        public Action OkAction { get; set; }
        public Action CancelAction { get; set; }
        public Action YesAction { get; set; }
        public Action NoAction { get; set; }
    
        public enum Style
        {
            Ok,
            YesNo
        }
    }
    

    【讨论】:

    • 这应该不起作用,因为调用活动可能会被 Android 销毁/重新创建。唯一的成就是您的子视图模型阻止父活动实例从内存中释放。
    • 这确实有效。但你是对的,调用活动可能会被破坏。尽管如此,从实际的角度来看,您的对话很可能是非常简单的活动,它可能不会导致调用者被挤出内存。我在许多设备上对此进行了测试,但仍未让我失望。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    相关资源
    最近更新 更多