У меня есть приложение, которое загружает записи из двоичного файла журнала и отображает их в виртуальном TListView. В файле есть потенциально миллионы записей, и дисплей может быть отфильтрован пользователем, поэтому я не загружаю все записи в памяти за один раз, а индексы элементов ListView не являются отношением 1 к 1 с смещения записи файла (например, элемент 1 списка может быть файловой записью 100). Я использую событие OnDataHint ListView для загрузки записей только для элементов, которые действительно интересуют ListView. По мере того, как пользователь прокручивается, диапазон, указанный OnDataHint, изменяется, что позволяет мне освобождать записи, которые не находятся в новом диапазоне, и выделять новые записи по мере необходимости.TVirtualStringTree - сброс невидимых узлов и потребление памяти
Это прекрасно работает, скорость переносима, а площадь памяти очень низкая.
В настоящее время я оцениваю TVirtualStringTree как замену TListView, главным образом потому, что хочу добавить возможность разворачивать/сворачивать записи, охватывающие несколько строк (я могу выманить его с помощью TListView, увеличивая/уменьшая количество элементов динамически, но это не так прямо, как использование реального дерева).
По большей части, я смог поместить логику TListView и все, что мне нужно. Я заметил, что виртуальная парадигма TVirtualStringTree значительно отличается. Он не имеет такой же функции OnDataHint, что и TListView (я могу использовать событие OnScroll для подделки, что позволяет моей логике буфера памяти продолжать работать), и я могу использовать событие OnInitializeNode для связывания узлов с выделенными записями ,
Однако, как только узел дерева инициализирован, он видит, что он остается инициализированным для времени жизни дерева. Это не хорошо для меня. Когда пользователь прокручивается и я удаляю записи из памяти, мне нужно сбросить эти невизуальные узлы, не удаляя их полностью из дерева или не теряя состояния разложения/сглаживания. Когда пользователь прокручивает их обратно в представлении, я могу перераспределить записи и повторно инициализировать узлы. В принципе, я хочу сделать TVirtualStringTree максимально похожим на TListView, насколько это касается его виртуализации.
Я видел, что TVirtualStringTree имеет метод ResetNode(), но каждый раз, когда я пытаюсь его использовать, я сталкиваюсь с различными ошибками. Я должен использовать это неправильно. Я также думал о простом хранении указателя данных внутри каждого узла в своих буферах записи, и я выделяю и освобождаю память, соответственно обновляю эти указатели. Конечный эффект тоже не работает.
Хуже того, мой самый большой файл журнала испытаний имеет ~ 5 миллионов записей в нем. Если я инициализирую TVirtualStringTree с таким количеством узлов за один раз (когда отображение журнала не фильтруется), внутренние накладные расходы дерева для его узлов занимают колоссальную 260 МБ памяти (без каких-либо еще выделенных записей). В то время как с TListView, загружая тот же файл журнала и всю логику памяти позади него, я могу уйти с использованием всего нескольких МБ.
Любые идеи?
В настоящее время я использую TListView в режиме vsReport, а не TListBox. TListView не поддерживает элементы переменной высоты в vsReport. –
Я отмечаю это как ответ на данный момент, но только потому, что он говорит мне не переключиться на VST. –