众所周知,在代码中挂接事件处理时,我们冒着将对象保留在内存中的风险,从而造成内存泄漏。
为了实现某些特殊功能(禁用剪切和复制),我需要在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
不为空的检查,但是我从未看到有任何证明被调用的证据。
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;
}
}
从用户界面中删除控件后,应该清除这些渲染器,然后触发OnElementChanged
方法吗?
答案 0 :(得分:2)
在此处查看有关自定义渲染器的文章:Implementing a View 它包含自定义渲染器的OnElementChanged方法的模板:
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时挂接它们。
至于评论中的后续问题(如果未触发第二个以上条件,我们应该退订):我的理解是,这两个对象(因此,渲染器和本机控件)的生存期是相同的,因此这种情况下,无需手动取消订阅事件。如果我错了,请纠正我。