Search code examples
c#xamarinmvvmreactive-property

ReactiveProperty initial value


I'm trying to set an initial value to the public ReactiveProperty<string> ConnectionStatus.

public ViewModelConstructor()
{
    ConnectionStatus = Observable
                    .Interval(RefreshInterval)
                    .Select(x => Observable.FromAsync(() => networkDiscovererService.CanDiscoverAsync("192.168.1.1", RequestTimeout)))
                    .Concat()
                    .Select(isConnected => isConnected ? $"connected" : $"not connected")
                    .ToReactiveProperty();
}

Even if I'm trying to instantiate it like this

public ReactiveProperty<string> ConnectionStatus { get; } =
            new ReactiveProperty<string>("Checking connectivity...");

It's still empty until the observable returns something.

Any ideas? I'm using this library.


Solution

  • To get initial value on subscribe (like behaviorSubject, or Replay(1)) using ReactiveProperty ctor:

        [Test]
        public void ShouldReturnAValuOnSubscribe()
        {
            var testScheduler = new TestScheduler();
            var testableObserver = testScheduler.CreateObserver<int>();
    
            var reactiveProperty = new ReactiveProperty<int>(30);
            reactiveProperty.Subscribe(testableObserver);
    
            Assert.AreEqual(30, testableObserver.Messages.Single().Value.Value);
        }
    

    To get initial value on subscribe (like behaviorSubject, or Replay(1)) using .ToReactiveProperty():

        [Test]
        public void ShouldReturnAValuOnToReactiveProperty()
        {
            var testScheduler = new TestScheduler();
            var testableObserver = testScheduler.CreateObserver<int>();
    
            var reactiveProperty = Observable.Never<int>().ToReactiveProperty(40);
            reactiveProperty.Subscribe(testableObserver);
    
            Assert.AreEqual(40, testableObserver.Messages.Single().Value.Value);
        }
    

    NOT to get initial value on subscribe - change ReactivePropertyMode:

        [Test]
        public void ShouldNotReturnAnInitialValue_WhenModeIsNone_AndOnSubscribe()
        {
            var testScheduler = new TestScheduler();
            var testableObserver = testScheduler.CreateObserver<int>();
    
            var reactiveProperty = new ReactiveProperty<int>(30, ReactivePropertyMode.None);
            reactiveProperty.Subscribe(testableObserver);
    
            Assert.IsEmpty(testableObserver.Messages);
        }
    

    Basically, what you're looking for is initial value and ReactivePropertyMode.RaiseLatestValueOnSubscribe flag.

    In the first case you forgot to provider ToReactiveProperty() with initial value (e.g. ToReactiveProperty(30))

    It should've worked for you in the second case - the mode is set to ReactivePropertyMode.RaiseLatestValueOnSubscribe by default (check ShouldReturnAValuOnSubscribe). Try to set the mode explicitly (like in ShouldNotReturnAnInitialValue_WhenModeIsNone_AndOnSubscribe).

    I used ReactiveProperty 3.6.0.

    btw, It's not a very good idea to test a connection based on timer :)