反应性扩展:如何忽略短暂的状态变化
Reactive Extensions: How to ignore short state changes
我想从我的 Xamarin 应用程序观察 Internet 连接的状态变化。我使用 Connectivity Plugin,它提供了一个 ConnectivityChanged 事件,我将其转换为一个 Observable。这很好用。
问题是电话切换时,例如从 3G 到 4G 有一个短暂的断开连接,我想忽略它。
到目前为止,我尝试使用 Throttle
和 Distinct
直到更改但没有运气,因为即使状态与断开连接之前相同,我总是得到一个值。
到目前为止我试过这个:
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 它的发生。
我想从我的 Xamarin 应用程序观察 Internet 连接的状态变化。我使用 Connectivity Plugin,它提供了一个 ConnectivityChanged 事件,我将其转换为一个 Observable。这很好用。
问题是电话切换时,例如从 3G 到 4G 有一个短暂的断开连接,我想忽略它。
到目前为止,我尝试使用 Throttle
和 Distinct
直到更改但没有运气,因为即使状态与断开连接之前相同,我总是得到一个值。
到目前为止我试过这个:
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 它的发生。