何时取消挂钩 Xamarin 自定义渲染器中的事件

众所周知,当在代码中连接事件处理时,我们冒着将对象留在内存中的风险,从而造成内存泄漏。


为了实现一些特殊功能(禁用剪切和复制),我需要在 UWP 上实现自定义渲染器。虽然禁用剪切和复制与我必须连接事件处理程序才能实现这一点的问题并不严格相关。


protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)

{

    base.OnElementChanged(e);


    if (this.Control == null) { return; }


    this.Control.CopyingToClipboard += Control_CopyingToClipboard;

    this.Control.CuttingToClipboard += Control_CuttingToClipboard;

}


private void Control_CuttingToClipboard(TextBox sender, 

                                        TextControlCuttingToClipboardEventArgs args)

{

    args.Handled = true;

}


private void Control_CopyingToClipboard(TextBox sender, 

                                        TextControlCopyingToClipboardEventArgs args)

{

    args.Handled = true;

}

问题


解开这些事件处理程序以防止任何形式的泄漏的正确位置是什么?


我注意到平台名称空间中IDisposable没有实现VisualElementRenderer<TElement, TNativeElement>,UWP但是我无法可靠地证明它被调用了。


更新


根据Michał Żołnieruk的建议,我在OldElement不为 null的检查中添加了 unhooking,但我从未看到任何证据证明这会被调用。


protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)

{

    base.OnElementChanged(e);


    if (this.Control == null) { return; }


    if (e.OldElement != null)

    {

        System.Debug.WriteLine("I NEVER SEE THIS");


        this.Control.CopyingToClipboard -= Control_CopyingToClipboard;

        this.Control.CuttingToClipboard -= Control_CuttingToClipboard;

    }


    if (e.NewElement != null)

    {

        this.Control.CopyingToClipboard += Control_CopyingToClipboard;

        this.Control.CuttingToClipboard += Control_CuttingToClipboard;

    }

}

当从 UI 中删除控件时,是否应该清理这些渲染器并因此触发该OnElementChanged方法?


开满天机
浏览 160回答 1
1回答

至尊宝的传说

在此处查看有关自定义渲染器的文章:实现视图 它包含自定义渲染器的 OnElementChanged 方法的模板:protected override void OnElementChanged (ElementChangedEventArgs<NativeListView> e){&nbsp; base.OnElementChanged (e);&nbsp; if (Control == null) {&nbsp; &nbsp; // Instantiate the native control and assign it to the Control property with&nbsp; &nbsp; // the SetNativeControl method&nbsp; }&nbsp; if (e.OldElement != null) {&nbsp; &nbsp; // Unsubscribe from event handlers and cleanup any resources&nbsp; }&nbsp; if (e.NewElement != null) {&nbsp; &nbsp; // Configure the control and subscribe to event handlers&nbsp; }}因此,您应该在 OldElement 不为 null 时取消挂钩事件,并在出现 NewElement 时挂钩它们。至于评论中的后续问题(如果上面的第二个没有被触发,我们是否应该取消订阅):我的理解是这两个对象的生命周期(所以渲染器和本机控件)是相同的,在这种情况下没有需要手动取消订阅事件。如果我错了,请纠正我。
打开App,查看更多内容
随时随地看视频慕课网APP