0

I'm having difficulties understanding how renderers work on Android side.

I'm trying to implement a MasterDetail page in my app. It should work on old devices, so I'm creating my pages during the application start, store them and switch Detail to those pages for a smoother user experience.

Let's say I have a custom entry on the first page, it is working fine but when I switch to page2 and then come back on page1, I'm not able to use the Control variable from my renderer anymore because it got disposed. Well, I can't when i'm using it in an event but it works as usual in the OnElementChanged method which is called when the page is appearing.

Can someone explain me how to still be able to access the renderer's Control variable when my events are triggered?

Here is my renderer class

public class EntryIncroyableRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            if(e.NewElement != null)
            {
                Control.InputType = 0;
                Control.EditorAction += (sender, args) =>
                {
                    if ((args.ActionId == ImeAction.ImeNull && args.Event.Action == KeyEventActions.Down) || args.ActionId == ImeAction.Done)
                    {
                        (e.NewElement as EntryIncroyable)?.EnterPressed();
                    }
                };

                (e.NewElement as EntryIncroyable).OnFocused_TriggerRenderer += MyEntryRenderer_FocusControl;
                (e.NewElement as EntryIncroyable).OnHideKeyBoard_TriggerRenderer += MyEntryRenderer_HideKeyboard;
            }
        }

        void MyEntryRenderer_HideKeyboard()
        {
            HideKeyboard();
        }

        void MyEntryRenderer_FocusControl(object sender, GenericEventArgs<FocusArgs> args)
        {
            args.EventData.CouldFocusBeSet = Control.RequestFocus();
            if (!((EntryIncroyable)Element).CanShowVirtualKeyboard)
            {
                HideKeyboard();
            }
        }

        public void HideKeyboard()
        {
            Control.RequestFocus();
            if (!((EntryIncroyable)Element).CanShowVirtualKeyboard)
                {
                    Control.InputType = 0;
                    InputMethodManager imm = Control.Context.GetSystemService(Context.InputMethodService) as InputMethodManager;
                    imm.HideSoftInputFromWindow(Control.WindowToken, HideSoftInputFlags.None);
                }
                else
                {
                    Control.InputType = Android.Text.InputTypes.ClassText;
                    InputMethodManager imm = Control.Context.GetSystemService(Context.InputMethodService) as InputMethodManager;
                    imm.ShowSoftInput(this, ShowFlags.Implicit);
                }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
        }
    } 

1 Answers1

0

I found what was the problem. My events were called from the disposed renderer since i didn't unsubcribe from it. I tried to do it in the OnElementChanged method with the (e.OldElement != null) condition but it was never true. So I unsubscribed my events in the dispose method.

protected override void Dispose(bool disposing)
        {
            (Element as EntryIncroyable).OnFocused_TriggerRenderer -= MyEntryRenderer_FocusControl;
            (Element as EntryIncroyable).OnHideKeyBoard_TriggerRenderer -= MyEntryRenderer_HideKeyboard;
            base.Dispose(disposing);
        }