John
John

Reputation: 601

Leak on a custom view loaded in a xaml

One of my activity is never disposed as one of its subviews registers to an event handler and never unregisters it, I tried to unregister it in the subview Dispose method but its never called.

The subview use an event handler CrossConnectivity to shows itself when network connection is down and hide itself when the connection is up again.

This subview is referenced in the layout axml so its instantiated when the layout is inflated.

The activity which only loads a layout

using Android.App;
using Android.OS;

namespace MyNamespace
{
    [Activity(Label = "SimpleActivity")]
    public class SimpleActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.SimpleLayout);
        }
    }
}

The said layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <MyNamespace.NetworkStateView
        android:text="No network"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textViewNetworkState" />
</LinearLayout>

The custom view

using System;
using Android.Content;
using Android.Util;
using Android.Views;
using Android.Widget;
using Connectivity.Plugin;
using Connectivity.Plugin.Abstractions;

namespace MyNamespace
{
    public class NetworkStateView : TextView
    {
        public NetworkStateView(Context ctx) : base(ctx)
        {
        }

        public NetworkStateView(IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer) : base(javaReference, transfer)
        {
        }

        public NetworkStateView(Context context, IAttributeSet attrs) : base(context, attrs)
        {
        }

        protected override void OnFinishInflate()
        {
            base.OnFinishInflate();
            BindConnectivity();
        }

        void BindConnectivity()
        {
            CrossConnectivity.Current.ConnectivityChanged += OnConnectivityChanged;
            UpdateVisibility();
        }

        void OnConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
        {
            UpdateVisibility();
        }

        void UpdateVisibility()
        {
            Visibility = CrossConnectivity.Current.IsConnected ? ViewStates.Gone : ViewStates.Visible;
        }

        protected override void Dispose(bool disposing)
        {
            CrossConnectivity.Current.ConnectivityChanged -= OnConnectivityChanged;
            base.Dispose(disposing);
        }
    }
}

Upvotes: 1

Views: 341

Answers (1)

John
John

Reputation: 601

I finally found a way to solve it while writing the question, I override OnDetachedFromWindow and remove the event handler in it

protected override void OnDetachedFromWindow()
{
    base.OnDetachedFromWindow();
    CrossConnectivity.Current.ConnectivityChanged -= OnConnectivityChanged;
}

Upvotes: 2

Related Questions