Convert Android Lifecycle Callback to Reactive Observable
Asked Answered
K

1

0

How do I convert an Android lifecycle callback to a RX Observable?

For example, onNewIntent. I could make my Activity itself a custom Observable, calling onNext for a bunch of Observers within onNewIntent - but that feels yucky. I would rather not implement a home-brew Observable if I can help it, so as to not need to mess with multi-threading etc.

namespace ...
{
    using ...

    /// <summary>
    /// Main application activity.
    /// </summary>
    [Activity(...)]
    public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IObservable<Intent>
    {
        private List<IObserver<Intent>> observers;

        ...

        /// <inheritdoc/>
        public IDisposable Subscribe(IObserver<Intent> observer)
        {
            this.observers.Add(observer);
            return new Unsubscriber(this.observers, observer);
        }

        /// <inheritdoc/>
        protected override void OnNewIntent(Intent intent)
        {
            foreach (var observer in this.observers)
            {
                observer.OnNext(intent);
            }
        }

        private class Unsubscriber : IDisposable
        {
            private List<IObserver<Intent>> observers;
            private IObserver<Intent> observer;
            private bool disposedValue;

            public Unsubscriber(
                List<IObserver<Intent>> observers,
                IObserver<Intent> observer)
            {
                this.observers = observers;
                this.observer = observer;
            }

            public void Dispose()
            {
                // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
                this.Dispose(disposing: true);
                GC.SuppressFinalize(this);
            }

            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposedValue)
                {
                    // dispose managed state (managed objects)
                    if (disposing &&
                        this.observer != null &&
                        this.observers.Contains(this.observer))
                    {
                        this.observers.Remove(this.observer);
                    }

                    // set large fields to null
                    this.observers = null;
                    this.observer = null;

                    this.disposedValue = true;
                }
            }
        }
    }
}

If there was something like a NewIntent event, this would be an easier question - there are creation operators for events, delegates, etc. But these all work with the event from outside the event - with something like an onNewIntent override implementation, I'm already inside the event (inside the monad?). So I don't know how to invert that.

Kerouac answered 26/1, 2022 at 16:3 Comment(2)
Or dare I say it, is this the time to use a Subject?Kerouac
Take a look at Reactive Extensions (Rx.NET) , maybe helpful .Demodena
K
0

I've come up with a solution. Not sure it's the most elegant, but it basically involves creating an additional event that I raise when handling the callback. Then it's just a quick trip to FromEventPattern and hey presto! Observable event data. Would be happy to hear if anyone else has any alternate approaches, but this seems to work.

namespace ...
{
    using ...

    /// <summary>
    /// Main application activity.
    /// </summary>
    [Activity(...)]
    public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IWithNewIntentObservable
    {
        private event EventHandler<Intent> NewIntent;

        /// <inheritdoc/>
        public IObservable<Intent> NewIntentObservable { get; private set; }

        ...

        /// <inheritdoc/>
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            ...

            this.NewIntentObservable = Observable.FromEventPattern<Intent>(
                h => this.NewIntent += h,
                h => this.NewIntent -= h).Select(e => e.EventArgs);
        }

        /// <inheritdoc/>
        protected override void OnNewIntent(Intent intent)
        {
            this.NewIntent?.Invoke(this, intent);
        }
    }
}
Kerouac answered 27/1, 2022 at 19:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.