反应性扩展:如何忽略短暂的状态变化

Reactive Extensions: How to ignore short state changes

我想从我的 Xamarin 应用程序观察 Internet 连接的状态变化。我使用 Connectivity Plugin,它提供了一个 ConnectivityChanged 事件,我将其转换为一个 Observable。这很好用。

问题是电话切换时,例如从 3G 到 4G 有一个短暂的断开连接,我想忽略它。

到目前为止,我尝试使用 ThrottleDistinct 直到更改但没有运气,因为即使状态与断开连接之前相同,我总是得到一个值。

到目前为止我试过这个:

var connectionEvent = Observable.FromEventPattern<ConnectivityChangedEventHandler, ConnectivityChangedEventArgs>( 处理程序 => handler.Invoke, h => CrossConnectivity.Current.ConnectivityChanged += h, h => CrossConnectivity.Current.ConnectivityChanged -= h) .Select(x => x.EventArgs.IsConnected) .油门(TimeSpan.FromSeconds(5)) .DistinctUntilChanged()<br> .StartWith(CrossConnectivity.Current.IsConnected) 。发布();

很难弄清楚 "Stuff's firing when I don't want it to" 发生了什么。幸运的是,Rx 有一些强大的测试支持。这是一些测试代码(使用 Nuget Install-Package Microsoft.Reactive.Testing)。 source 表示来自 Android API 的噪声。 target 是您在其之上的一组运算符。 expectedResults是结果:

TestScheduler ts = new TestScheduler();
var crossConnectivity_Current_IsConnected = true;
var source = ts.CreateHotObservable<bool>(
    new Recorded<Notification<bool>>(200.MsTicks(), Notification.CreateOnNext(false)),
    new Recorded<Notification<bool>>(300.MsTicks(), Notification.CreateOnNext(true)),
    new Recorded<Notification<bool>>(5550.MsTicks(), Notification.CreateOnNext(false)),
    new Recorded<Notification<bool>>(5600.MsTicks(), Notification.CreateOnNext(true)),
    new Recorded<Notification<bool>>(5800.MsTicks(), Notification.CreateOnNext(false)),
    new Recorded<Notification<bool>>(7700.MsTicks(), Notification.CreateOnNext(true)),
    new Recorded<Notification<bool>>(7800.MsTicks(), Notification.CreateOnNext(false)),
    new Recorded<Notification<bool>>(13000.MsTicks(), Notification.CreateOnNext(true))
);

var target = source
    .Throttle(TimeSpan.FromSeconds(5), ts)
    .DistinctUntilChanged()
    .StartWith(crossConnectivity_Current_IsConnected);

var expectedResults = ts.CreateHotObservable<bool>(
    new Recorded<Notification<bool>>(0.MsTicks(), Notification.CreateOnNext(true)),
    new Recorded<Notification<bool>>(5300.MsTicks(), Notification.CreateOnNext(true)),
    new Recorded<Notification<bool>>(12800.MsTicks(), Notification.CreateOnNext(false)),
    new Recorded<Notification<bool>>(18000.MsTicks(), Notification.CreateOnNext(true))
);

我看到的唯一问题是 5300 处的通知。您可以通过 re-ordering 操作员稍微摆脱它。看看我的target2:

var target2 = source
    .Throttle(TimeSpan.FromSeconds(5), ts)
    .StartWith(crossConnectivity_Current_IsConnected)
    .DistinctUntilChanged()
    ;

var expectedResults2 = ts.CreateHotObservable<bool>(
    new Recorded<Notification<bool>>(0.MsTicks(), Notification.CreateOnNext(true)),
    new Recorded<Notification<bool>>(12800.MsTicks(), Notification.CreateOnNext(false)),
    new Recorded<Notification<bool>>(18000.MsTicks(), Notification.CreateOnNext(true))
);

...如果你想 运行 测试,这里是 运行ner 代码。

var observer = ts.CreateObserver<bool>();
target.Subscribe(observer);
var observer2 = ts.CreateObserver<bool>();
target2.Subscribe(observer2);
ts.Start();

ReactiveAssert.AreElementsEqual(expectedResults.Messages, observer.Messages);
ReactiveAssert.AreElementsEqual(expectedResults2.Messages, observer2.Messages);

...您将需要这个 class

public static class Extensions
{
    public static long MsTicks(this int i)
    {
        return TimeSpan.FromMilliseconds(i).Ticks;
    }
}

如果这不能解决您的问题,请扩充 source 来描述 when/how 它的发生。