跟踪动态数据过滤器和排序的执行 [英] Tracking the execution of dynamic data filters and sorts

查看:92
本文介绍了跟踪动态数据过滤器和排序的执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ReactiveUI建议以后使用动态数据。我尝试迁移必须在视图模型中工作的有意义的对象。

ReactiveUI recommends the use of dynamic-data going forward. I try to migrate what make sense as I have to work in my view models .

最近我遇到了一个我似乎无法找到的问题一个解决方案。在我的其中一页中,动态数据与 SourceCache 一起使用100,000个项目,我需要在这些项目上应用动态过滤器和排序。

Recently I've been facing a problem that I just can't seem able to find a solution to. In one of my pages, dynamic data is used with a SourceCache of 100,000 items on which I need to apply dynamic filters and sorts.

此问题是,即使在移动设备上发生100,000个过滤操作相对较快,用户也不知道我们是否完成过滤。让用户知道我们正在做某事的最简单方法是在我的 ListView 上使用 IsRefreshing

This issue is that even if filtering on 100,000 happens relatively fast on a mobile device the user has no idea if we are done filtering or not. The easiest way to let the user know we're doing something is using IsRefreshing on my ListView.

这是问题开始的地方...

This is where the problem starts...

我知道何时过滤开始,因为我是构建Observable触发器的人,所以我只是找不到可靠的方式来知道何时过滤完成(并非总是如此)。

I'm able to know when filtering starts since I'm the one building the Observable trigger, I just can't find a reliable way to know when the filtering completes (not always).

第一次运行过滤器并返回0结果将按预期工作,它将不会在初始时间之后再次触发0结果(更改),直到达到结果中至少有一个更改。

The first time a filter runs and returns 0 results things work as expected, it just won't trigger 0 results (changes) again after the initial time until we get at least one change in the results.

这意味着只要过滤器对结果集产生更改,我就可以显示和隐藏刷新微调器。用户点击0个结果,随后的0个结果搜索将对结果进行0次更改,并且不会触发可观察 ...微调框将一直旋转直到过滤器产生至少1次更改。

This means that I can show and hide a refresh spinner as long as the filter yields "changes" to the result set but as soon as the user hits 0 results, subsequent 0 result searches will yield 0 changes to the results and won't trigger the Observable... The spinner will just keep on spinning until a filter yields at least 1 change.

这里的代码说明了这个问题:(为简单起见,使用 SourceList

Here's code to that illustrates the issue: (using a SourceList for simplicity)

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的任何结果:

This code give the following results.. notice how I don't get any results for 100002 and 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变化而触发,因为我只是运行了一个过滤器,并且很有可能对结果感兴趣。

I would have expected the Observable to trigger even if it is with 0 changes since I just ran a filter and am most likely interested in the outcome.

任何人都知道如何解决这个问题?我做错什么了吗?

Anyone has any idea how to get around this? Am I doing something wrong?

推荐答案

您所观察到的问题是由历史性设计决定抑制我发出的空通知引起的在动态数据的早期。这是出于性能原因。我正在开发一个非常繁忙的交易系统,该系统每秒在大型数据集上动态过滤几次。结果被作为派生的缓存公开,随后被数十个其他函数使用。抑制空白结果可为该系统的性能带来奇迹。但是,该决定很糟糕,因为它有副作用,给您带来沉重打击。

The problem you have observed is caused by the historic design decision to suppress empty notifications which I made during the early days of Dynamic Data. This was for performance reasons. I was developing an extremely busy trading system which was dynamically filtering several times a second on a large data set. The result was exposed as a derived cache which was subsequently consumed by dozens of other functions. Suppressing empty results worked wonders for the performance of that system. However the decision was poor as it has had the side effect which has hit you hard.

一个更好的解决方案是消除该限制,并允许消费者使用 .NotEmpty()运算符选择这样做。这样做可以消除您的问题。

A much better solution would be for that restriction be removed and allow consumers to use the .NotEmpty() operator to opt in. Doing so would remove your issue.

请问您可以在Github上提交问题,我将取消限制。

Could you please submit an issue on Github and I will remove the restriction.

这篇关于跟踪动态数据过滤器和排序的执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆