代码之家  ›  专栏  ›  技术社区  ›  Bijington

何时在Xamarin自定义呈现器中取消事件挂钩

  •  0
  • Bijington  · 技术社区  · 7 年前

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

    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 然而,我还不能可靠地证明它被调用了。

    更新

    米夏奥尼鲁克 我的建议是在支票内为 OldElement

    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 方法?

    1 回复  |  直到 7 年前
        1
  •  4
  •   Michał Å»ołnieruk    7 年前

    Implementing a View 它包含自定义呈现器的OneElementChanged方法的模板:

    protected override void OnElementChanged (ElementChangedEventArgs<NativeListView> e)
    {
      base.OnElementChanged (e);
    
      if (Control == null) {
        // Instantiate the native control and assign it to the Control property with
        // the SetNativeControl method
      }
    
      if (e.OldElement != null) {
        // Unsubscribe from event handlers and cleanup any resources
      }
    
      if (e.NewElement != null) {
        // Configure the control and subscribe to event handlers
      }
    }
    

    因此,应该在OldElement不为null时取消钩住事件,并在NewElement存在时钩住它们。

    至于评论中的后续问题(如果没有触发上面的第二个if,我们是否应该取消订阅):我的理解是,这两个对象(因此呈现器和本机控件)的生存期是相同的,在这种情况下,不需要手动取消订阅事件。如果我错了,请纠正我。

    推荐文章