Dbl Dbl - 1 month ago 12
Android Question

How can i pass an IDialogInterfaceOnDismissListener without my application crashing?

I've got an issue with my Xamarin.Android application regarding

IDialogInterfaceOnDismissListener
.

My repro sample:

public enum ConfirmationResult
{
Cancel,
Yes,
No
}

public interface IDialogService
{
Task<ConfirmationResult> ConfirmAsync(string title, string message, string acceptText, string declineText);
}

public class DialogService : IDialogService
{
class DismissDelegateListener : IDialogInterfaceOnDismissListener, IDialogInterfaceOnCancelListener
{
private Action _callback;

public DismissDelegateListener()
{

}

public DismissDelegateListener(Action callback)
{
_callback = callback;
}

public void Dispose()
{
_callback = null;
}

public IntPtr Handle { get; }

public void OnCancel(IDialogInterface dialog)
{
_callback?.Invoke();
}

public void OnDismiss(IDialogInterface dialog)
{
_callback?.Invoke();
}
}

private readonly WeakReference<Context> _activity;

public DialogService(Context activity)
{
_activity = new WeakReference<Context>(activity);
}

public async Task<ConfirmationResult> ConfirmAsync(string title, string message, string acceptText, string declineText)
{
Context target;
if (!_activity.TryGetTarget(out target))
return ConfirmationResult.Cancel;

TaskCompletionSource<ConfirmationResult> tcs = new TaskCompletionSource<ConfirmationResult>();

var builder = new AlertDialog.Builder(target);
var d = builder
.SetTitle(title)
.SetMessage(message)
.SetPositiveButton(acceptText, (sender, args) =>
{
tcs.SetResult(ConfirmationResult.Yes);
(sender as AlertDialog)?.Dispose();
})
.SetNegativeButton(declineText, (sender, args) =>
{
tcs.SetResult(ConfirmationResult.No);
(sender as AlertDialog)?.Dispose();
})
// if this line is uncommented my application crashes once the dialog is opened
// .SetOnCancelListener(new DismissDelegateListener(() => { tcs.SetResult(ConfirmationResult.Cancel); }))
.Create();

d.Show();

return await tcs.Task;
}
}


As soon as i call
SetOnCancelListener
my application will crash with the error message
System.InvalidCastException: Specified cast is not valid.


To me everything appears to be correct - i am passing an implementation of the requested interface and my implementation isn't all that difficult either.

Does this problem ring a bell to anyone?

Dbl Dbl
Answer

Deriving from Java.Lang.Object was the solution.

        class DismissDelegateListener : Java.Lang.Object, IDialogInterfaceOnDismissListener, IDialogInterfaceOnCancelListener
        //class DismissDelegateListener : IDialogInterfaceOnDismissListener, IDialogInterfaceOnCancelListener
        {
            private Action _callback;

            public DismissDelegateListener()
            {

            }

            public DismissDelegateListener(Action callback)
            {
                _callback = callback;
            }

            protected override void Dispose(bool disposing)
            {
                _callback = null;
                base.Dispose(disposing);
            }

            public void OnCancel(IDialogInterface dialog)
            {
                _callback?.Invoke();
            }

            public void OnDismiss(IDialogInterface dialog)
            {
                _callback?.Invoke();
            }
        }
Comments