我是否需要取消订阅 Click 事件以防止内存泄漏?

Do I need to unsubscribe Click event to prevent memory leaks?

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

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

那我就糊涂了。我应该取消订阅所有的点击事件吗?我觉得既然mButton是我的Activity的成员,那么在销毁我的Activity的时候,mButton也应该被销毁,所以没有必要取消订阅它的Click事件。是真的吗?如果是这样,那么在什么情况下我应该取消订阅活动?

谢谢!

绝对是!

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

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

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

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

我通常是这样做的

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;
    }