Отслеживание выполнения динамических фильтров данных и сортировок - PullRequest
0 голосов
/ 13 февраля 2019

ReactiveUI рекомендует использовать динамические данные в будущем.Я пытаюсь перенести то, что имеет смысл, поскольку мне приходится работать с моими моделями представлений.

Недавно я столкнулся с проблемой, которую, похоже, не могу найти решение.На одной из моих страниц динамические данные используются с SourceCache из 100 000 элементов, к которым мне нужно применить динамические фильтры и сортировки.

Эта проблема заключается в том, что даже если фильтрация по 100 000 происходит относительно быстро на мобильном устройстве пользователь не имеет представления, закончили ли мы фильтрацию или нет.Самый простой способ сообщить пользователю, что мы что-то делаем, - использовать IsRefreshing на моем ListView.

Вот здесь и начинается проблема ...

Я могу знать, когда фильтрация запускает , так как я строю триггер Observable, я просто могуНе найти надежный способ узнать, когда фильтрация завершается (не всегда).

В первый раз, когда фильтр запускается и возвращает 0 результатов, все работает, как и ожидалось, он просто не будет вызывать 0 результатов (изменений) снова после начального времени, пока мы не получим хотя бы одно изменение в результатах.

Это означает, что я могу показывать и скрывать счетчик обновления, пока фильтр дает «изменения» в наборе результатов, но как только пользователь выберет 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 изменениями, поскольку я только что запустил фильтр и, скорее всего, заинтересован в результате.

У кого-нибудь есть идеи, как обойти это?Я что-то не так делаю?

1 Ответ

0 голосов
/ 13 февраля 2019

Проблема, которую вы наблюдали, вызвана историческим решением о дизайне для подавления пустых уведомлений, которое я сделал в первые дни Dynamic Data.Это было из соображений производительности.Я разрабатывал чрезвычайно загруженную торговую систему, которая несколько раз в секунду динамически фильтровала большой набор данных.Результат был представлен как производный кеш, который впоследствии был использован десятками других функций.Подавление пустых результатов творит чудеса для производительности этой системы.Однако решение было плохим, поскольку у него был побочный эффект, который сильно ударил вас.

Гораздо лучшим решением было бы снятие этого ограничения, позволяющее потребителям использовать оператор .NotEmpty() для выбора. Это позволило бы устранить вашу проблему.

Не могли бы вы представить проблемуна Github и я сниму ограничение.

...