跟踪动态数据过滤器和排序的执行
Tracking the execution of dynamic data filters and sorts
ReactiveUI 建议以后使用动态数据。我尝试迁移有意义的东西,因为我必须在我的视图模型中工作。
最近我遇到了一个似乎无法找到解决方案的问题。在我的一个页面中,动态数据与 SourceCache
的 100,000 个项目一起使用,我需要对其应用动态过滤器和排序。
这个问题是,即使在移动设备上相对较快过滤 100,000,用户也不知道我们是否完成过滤。让用户知道我们正在做某事的最简单方法是在我的 ListView
上使用 IsRefreshing
。
这就是问题开始的地方...
我能够知道何时过滤 starts 因为我是构建 Observable 触发器的人,我只是找不到可靠的方法来知道何时过滤 完成(不总是)。
过滤器第一次运行并且 returns 0 个结果按预期工作,它不会在初始时间后再次触发 0 个结果(更改),直到我们得到至少一个结果更改.
这意味着只要过滤器对结果集产生 "changes",我就可以显示和隐藏刷新微调器,但是一旦用户点击 0 个结果,后续的 0 个结果搜索将产生 0 个更改结果并且不会触发 Observable...微调器将继续旋转直到过滤器产生至少 1 个变化。
下面是说明问题的代码:(为简单起见,使用 SourceList
)
var disposables = new CompositeDisposable();
var sourceList = new SourceList<string>();
ReadOnlyObservableCollection<string> results;
using (disposables)
{
// Create 100,000 dummy strings to start with
sourceList.Edit(
(innerList) =>
{
Enumerable
.Range(1, 100000)
.ForEach(x => innerList.Add(x.ToString()));
});
// Fake text trigger to replicate WhenAnyValue
var trigger = new Subject<string>();
disposables.Add(trigger);
// Dynamic filter
var filter = trigger
.Do(s =>
{
Console.WriteLine($"\r\nSearching for: {s}");
})
.Select(
searchTerm =>
{
Func<string, bool> searcher = item => item.StartsWith(
searchTerm,
StringComparison.InvariantCultureIgnoreCase);
return searcher;
});
disposables.Add(
sourceList
.Connect()
.Filter(filter)
.Bind(out results)
.Subscribe(
x =>
{
Console.WriteLine($"Got {results.Count} results");
}));
// Those works as expected
trigger.OnNext("99999");
trigger.OnNext("9999");
trigger.OnNext("9998");
trigger.OnNext("1");
trigger.OnNext("100001");
// At this point, because there aren't any changes we don't get any more results
// until we return something other than 0 items.
trigger.OnNext("100002");
trigger.OnNext("100003");
// This will get results as expected.
trigger.OnNext("99998");
}
这段代码给出了以下结果。请注意我没有得到 100002 和 100003 的任何结果:
Searching for: 99999
Got 1 results
Searching for: 9999
Got 11 results
Searching for: 9998
Got 11 results
Searching for: 1
Got 11112 results
Searching for: 100001
Got 0 results
Searching for: 100002
Searching for: 100003
Searching for: 99998
Got 1 results
我原以为 Observable 会触发,即使它有 0 个更改,因为我只是 运行 一个过滤器并且很可能对结果感兴趣。
有人知道如何解决这个问题吗?我做错了什么吗?
您观察到的问题是由我在动态数据早期所做的禁止空通知的历史设计决定引起的。这是出于性能原因。我正在开发一个非常繁忙的交易系统,该系统每秒对一个大数据集进行多次动态过滤。结果作为派生缓存公开,随后被许多其他函数使用。抑制空结果为该系统的性能创造了奇迹。然而,这个决定很糟糕,因为它产生了对你打击很大的副作用。
更好的解决方案是取消该限制并允许消费者使用 .NotEmpty()
运算符选择加入。这样做会解决您的问题。
能否在 Github 上提交问题,我会取消限制。
ReactiveUI 建议以后使用动态数据。我尝试迁移有意义的东西,因为我必须在我的视图模型中工作。
最近我遇到了一个似乎无法找到解决方案的问题。在我的一个页面中,动态数据与 SourceCache
的 100,000 个项目一起使用,我需要对其应用动态过滤器和排序。
这个问题是,即使在移动设备上相对较快过滤 100,000,用户也不知道我们是否完成过滤。让用户知道我们正在做某事的最简单方法是在我的 ListView
上使用 IsRefreshing
。
这就是问题开始的地方...
我能够知道何时过滤 starts 因为我是构建 Observable 触发器的人,我只是找不到可靠的方法来知道何时过滤 完成(不总是)。
过滤器第一次运行并且 returns 0 个结果按预期工作,它不会在初始时间后再次触发 0 个结果(更改),直到我们得到至少一个结果更改.
这意味着只要过滤器对结果集产生 "changes",我就可以显示和隐藏刷新微调器,但是一旦用户点击 0 个结果,后续的 0 个结果搜索将产生 0 个更改结果并且不会触发 Observable...微调器将继续旋转直到过滤器产生至少 1 个变化。
下面是说明问题的代码:(为简单起见,使用 SourceList
)
var disposables = new CompositeDisposable();
var sourceList = new SourceList<string>();
ReadOnlyObservableCollection<string> results;
using (disposables)
{
// Create 100,000 dummy strings to start with
sourceList.Edit(
(innerList) =>
{
Enumerable
.Range(1, 100000)
.ForEach(x => innerList.Add(x.ToString()));
});
// Fake text trigger to replicate WhenAnyValue
var trigger = new Subject<string>();
disposables.Add(trigger);
// Dynamic filter
var filter = trigger
.Do(s =>
{
Console.WriteLine($"\r\nSearching for: {s}");
})
.Select(
searchTerm =>
{
Func<string, bool> searcher = item => item.StartsWith(
searchTerm,
StringComparison.InvariantCultureIgnoreCase);
return searcher;
});
disposables.Add(
sourceList
.Connect()
.Filter(filter)
.Bind(out results)
.Subscribe(
x =>
{
Console.WriteLine($"Got {results.Count} results");
}));
// Those works as expected
trigger.OnNext("99999");
trigger.OnNext("9999");
trigger.OnNext("9998");
trigger.OnNext("1");
trigger.OnNext("100001");
// At this point, because there aren't any changes we don't get any more results
// until we return something other than 0 items.
trigger.OnNext("100002");
trigger.OnNext("100003");
// This will get results as expected.
trigger.OnNext("99998");
}
这段代码给出了以下结果。请注意我没有得到 100002 和 100003 的任何结果:
Searching for: 99999
Got 1 results
Searching for: 9999
Got 11 results
Searching for: 9998
Got 11 results
Searching for: 1
Got 11112 results
Searching for: 100001
Got 0 results
Searching for: 100002
Searching for: 100003
Searching for: 99998
Got 1 results
我原以为 Observable 会触发,即使它有 0 个更改,因为我只是 运行 一个过滤器并且很可能对结果感兴趣。
有人知道如何解决这个问题吗?我做错了什么吗?
您观察到的问题是由我在动态数据早期所做的禁止空通知的历史设计决定引起的。这是出于性能原因。我正在开发一个非常繁忙的交易系统,该系统每秒对一个大数据集进行多次动态过滤。结果作为派生缓存公开,随后被许多其他函数使用。抑制空结果为该系统的性能创造了奇迹。然而,这个决定很糟糕,因为它产生了对你打击很大的副作用。
更好的解决方案是取消该限制并允许消费者使用 .NotEmpty()
运算符选择加入。这样做会解决您的问题。
能否在 Github 上提交问题,我会取消限制。