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