Xamarin.Forms Android 的自定义渲染器(条目)中的 OnElementChanged 仅被调用一次

OnElementChanged in custom renderer (Entry) for Xamarin.Forms Android is only being called once

我相信 OnElementChanged 应该被调用两次:一次是在创建控件时,一次是在它被释放时。这对我的 iOS 自定义渲染器按预期工作,但在 Android 自定义渲染器中没有。

在 iOS 中,当页面显示时 e.NewElement 是控件,e.OldElement 是空的。当显示下一页时,这个先前的控件似乎被处理掉了,因为 e.NewElement 是 null 而 e.OldElement 是那个控件。为新页面中的新控件调用 OnElementChanged。 Android.

不是这种情况

在 Android 中,每次显示带有控件的新屏幕时,都会调用 OnElementChanged 并将 e.OldElement 作为 null 并将 e.NewElement 作为控件(如预期)。但是,当显示切换到新屏幕时,不会为以前的 e.NewElement 为 null 的控件调用 OnElementChanged 方法。而是调用新页面上新控件的 OnElementChanged 方法。

为什么这个问题特别发生在 Android 中? 发生这种情况有什么原因吗?

我的目的是在处理该控件后安全地取消挂钩该事件。

iOS:

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace iOS.Renderers
{
    public class MyEntryRenderer: EntryRenderer
    {
        private UIButton _myButton = null;

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            // update control UI
            ...

            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                // Unsubscribe
                _myButton .TouchUpInside -= OnClearButtonTouched;
            }
            if (e.NewElement != null)
            {
                if (_myButton == null)
                {
                    // create button
                    _myButton = ...;
                }

                // Subscribe
                _myButton.TouchUpInside += OnClearButtonTouched;
            }
        }

        ...

    }
}

Android:

[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace Android.Renderers
{
    public class MyEntryRenderer: EntryRenderer
    {
        private FormsEditText _formsEditText;
        private Drawable _leftDrawable = null;

        public MyEntryRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            // update control UI
            ...

            base.OnElementChanged(e);

            // set appropriate event handler for when text is cleared

            if (_leftDrawable == null) {
                // get appropriate search drawable
                _leftDrawable = ...;
            }

            if (e.OldElement != null)
            {
                // Unsubscribe
                Control.AfterTextChanged -= AfterEntryTextChanged;
            }
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    _formsEditText = new FormsEditText(Context);
                    SetNativeControl(_formsEditText);
                }

                // Subscribe
                Control.AfterTextChanged += AfterEntryTextChanged;                    
            }
        }

        ...

    }
}

在 Android 取消挂钩 Dispose 中的事件:

bool _disposed;

protected override void Dispose(bool disposing)
{
    if (_disposed)
        return;

    _disposed = true;

    if (Control != null && disposing)
    {
        _myButton.TouchUpInside -= OnClearButtonTouched;
    }

    base.Dispose(disposing);
}  

另见 EntryRenderer and [Android] Effects don't detach and OnElementchanged(null) is never called #2520