【问题标题】:Do I need to unsubscribe Click event to prevent memory leaks?我是否需要取消订阅 Click 事件以防止内存泄漏?
【发布时间】:2016-04-27 14:41:42
【问题描述】:

我正在学习 Xamarin Android,我看到很多官方示例使用 lambdas 来订阅 Click 事件。像:mButton.Click += (sender, args) => { ... } 这样的东西很常见。我认为这种使用 lambda 的模式无法取消订阅事件。(如果我错了,请纠正我:))

今天我阅读了这份文件:Cross-Platform Performance - Unsubscribe from Events。它说我们应该取消订阅事件以防止内存泄漏。

那我就糊涂了。我应该取消订阅所有 Click 事件吗?我觉得由于mButton是我的Activity的成员,所以在销毁我的Activity时,mButton也应该被销毁,因此不需要取消订阅它的Click事件。是真的吗?如果是这样,那么在什么情况下我应该取消订阅活动?

谢谢!

【问题讨论】:

  • 你可以尝试使用 Rx 的魅力来处理事件吗,当你切换到这个模型时,你可能会发现很多内存泄漏都消失了。

标签: c# android memory-leaks xamarin xamarin.android


【解决方案1】:

我会说这取决于。只要没有保留引用并且垃圾收集器可以完成他的工作,您就不必这样做。但除此之外,最好这样做以防止内存泄漏。所以我更喜欢这样做。

要取消订阅 lambda 事件,只需将其存储在变量或字段中

EventHandler buttonOnClick = (sender, args) => button.Text = string.Format("{0} clicks!", count++);
button.Click += buttonOnClick;
button.Click -= buttonOnClick;

【讨论】:

    【解决方案2】:

    这就是我通常的做法

    protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
    
            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.LoginPage);
    
            InflateViews ();
    
        }
    
        protected override void OnResume ()
        {
            base.OnResume ();
    
            BindHandlers ();
        }
    
        protected override void OnPause ()
        {
            base.OnPause ();
    
            UnBindHandlers ();
        }
    
        void InflateViews()
        {
            loginButton = FindViewById (Resource.Id.loginButton);
            usernameField = FindViewById<EditText> (Resource.Id.userName);
            passwordField = FindViewById<EditText> (Resource.Id.password);
            forgotPassword = FindViewById (Resource.Id.forgotPassword);
        }
    
        void BindHandlers()
        {
            loginButton.Click+= LoginButton_Click;
            forgotPassword.Click+= ForgotPassword_Click;
        }
    
        void ForgotPassword_Click (object sender, EventArgs e)
        {
            StartActivity (typeof(ForgotPasswordActivity));
        }
    
        void UnBindHandlers()
        {
            loginButton.Click-= LoginButton_Click;
            forgotPassword.Click-= ForgotPassword_Click;
        }
    

    【讨论】:

    • 看起来很棒!我正在考虑实施这样的事情。一个后续问题。为什么 BindHandlers() 和 UnBindHandlers() 在 OnResume() 和 OnPause 中,而不是在 OnCreate() 和 OnStop 中?谢谢!
    • OnStop 不需要尽快调用,因为 Activity 被销毁或新的 Activity 启动。因此,有可能调用 OnCreate 但未调用 OnStop。但是 onresume /onpause 是一对非常棒的。当用户离开活动时,肯定会调用 OnPause
    【解决方案3】:

    绝对是的!

    为了防止内存泄漏,防止循环引用等很重要。花点时间搜索 SO,你会发现很多关于这个主题的信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      • 2012-02-29
      • 2019-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多