Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > TVirtualTreeView и "ленивая" загрузка


Автор: AnTeml 25.6.2014, 13:52
Здравствуйте. Использую любимый компонент TVirtualTreeView, теперь для работы с базой данных

Захотелось реализовать "ленивую" загрузку, благо тысячи элементов в VTV создаются без проблем и тормозов.


Подскажите, правильно ли я делаю? Реализация следующая. Из контролов - поле ввода (пусть это будет TEdit) и VirtualStringTree

для ленивой загрузки есть класс, LazyLoader, который при обращении к элементу по индексу либо выдаёт загруженный, либо загружает элементы с базы с Index-RowCount до Index+RowCount (ну или сколько влезло), так же выдаёт информацию об общем количестве элементов по запросу

Когда пользователь вводит запрос в поле свода - количество выгружаемых запросом данных меняется, поэтому на это событие (пусть будет OnEditChange) у меня назначено

Код

LazyLoader.SetRequestParameters(.....)  // там же происходит принудительная очистка списка
LazyLoader.GetItem(0);
VT.Clear;
VT.RootNodeCount := LazyLoader.GetCountTotalObjs;


Если пользователь не трогает Tedit, а прокручивает список - то LazyLoader соответственно выдаёт (подгружает) ему нужный элемент. Для получения нужного элемента мне достаточно знать индекс узла, поэтому на NodeData я вообще не завязываюсь:

Таким образом, я в любом событии, будь то VTGetText, VTGetHint, .. сначала вызываю 
Код

obj := LazyLoader[Node.Index]

ну а затем получаю из этого объекта текст и прочую информацию, которую вывожу

всё бы ничего, и всё работает, но что-то я подзадумался: а с какой скоростью вызываются GetText и прочие в VirtualTreeview? Точнее даже, синхронно или асинхронно? Не получится ли так, что при попытке отображения первого из полсотни элементов сервер притормозит с ответом, а в это время "выстрелит" события OnGetText  и прочие для остальных полсотни элементов, которые точно так же загрузят сервер своими запросами?

работает с виду всё нормально, но это пока сервер не загружен. Можно, конечно в отладке посмотреть, как это всё работает, но всё не выходит из головы сомнение, правильно ли я делаю, и не упустил ли я чего ещё?

Автор: kami 25.6.2014, 15:59
Цитата(AnTeml @  25.6.2014,  13:52 Найти цитируемый пост)
Не получится ли так, что при попытке отображения первого из полсотни элементов сервер притормозит с ответом, а в это время "выстрелит" события OnGetText  и прочие для остальных полсотни элементов, которые точно так же загрузят сервер своими запросами?

VT работает в VCL-потоке, с этим у него всё нормально. Поэтому, если сервер "притормозит" с ответом (и ответ получается "синхронно"), никакое событие не сможет возникнуть, пока не произойдет "расторможение".

Добавлено через 3 минуты и 11 секунд
Цитата(kami @  25.6.2014,  15:59 Найти цитируемый пост)
никакое событие не сможет возникнуть, пока не произойдет "расторможение".

Поправка - если в процессе "торможения" не будет вызван Application.ProcessMessages или его аналог. В качестве примера аналога могу привести методы ICS.THTTPCli.Get | Post

Автор: AnTeml 26.6.2014, 05:23
Спасибо!! Успокоили smile

Ну и мне не даёт покоя вопрос, правильно ли постоянно, очень часто изменять кол-во элементов в VTV, изменяя VT.RootNodeCount

то есть, как пример: выбор фамилии. При старте в VTV создалось 80 тыс фамилий людей (отображается реально десяток), если Вася Пупкин набирает свою фамилию, то после нажатия "П" VT.RootNodeCount уменьшится по кол-ву людей, фамилия которых начинается с "П" и в компоненте отобразится их первый десяток, добавил "у" - соответственно кол-во изменяется, в соответствии с кол-вом фамилий, начинающихся на "пу", и так далее... Пока Вася Пупкин наберёт свою фамилию - VT.RootNodeCount изменится шесть раз.

Ну и он весь день работает в таких компонентах.

Не возникает ли при таком потоке проблем, утечек памяти? Пока самые жесточайшие тесты ничего подобного не обнаружили, но что там в теории? Штатная ли такая работа?

На английском читаю очень медленно :( а больше ничего пока от VTV мне не требуется.

PS

На русском из литературы по  VTV нашёл только http://delphigears.blogspot.ru/2011/08/virtual-treeview.html
но там больше справочная краткая информация по одним из самых востребованных свойств (которая мне очень пригодилась)

о том, как работает компонент, как правильно его использовать при работе с массивами данных - информации практически нет :(


Автор: PointerToNil 26.6.2014, 08:05
на всякий случай: 
на оф.сайте VTV были примеры работы c DB 
ЕМНИП, под заголовком "Virtual Treeview and databases" - в режиме таблицы, а "addons" и/или "contributions" - в режиме дерева
в инете можно найти другие DB-компоненты, основанные на VTV - VirtualDBGrid (грид) и Dynamic DBTreeView (дерево)
(совместимость с последними дельфями не гарантирую, но как пример кода)

> Не возникает ли при таком потоке проблем, утечек памяти? 
в таком вопросе никому верить нельзя, проверяйте сами, FastMM4 + reportmemoryleaksonshutdown
http://www.gunsmoker.ru/2009/05/blog-post_24.html

> Пока самые жесточайшие тесты ничего подобного не обнаружили, но что там в теории? 
до жути странный вопрос! в теории всегда всё отлично же!!

Автор: kami 26.6.2014, 10:12
Цитата(AnTeml @  26.6.2014,  05:23 Найти цитируемый пост)
после нажатия "П" VT.RootNodeCount уменьшится по кол-ву людей, фамилия которых начинается с "П"

А зачем?
Проходим по нодам, "лишние" скрываем (Visible[Node]:=False). И всё - исходный список не трогается, AbsoluteIndex у нодов не меняется...

Автор: AnTeml 29.6.2014, 16:36
PointerToNil, спасибо! Давненько я Александра Алексеева не почитывал, а эту статью читал, но так как не пригождалось - забылось... ссылка прямо в точку! 

По поводу VirtualDBGrid - бегло глянул,  похоже, там компоненты для двузвенки. Я обращаюсь не к БД, а к серверу приложений, в принципе, моя схема меня удовлетворяет... пока....



Цитата(kami @  26.6.2014,  10:12 Найти цитируемый пост)
А зачем?Проходим по нодам, "лишние" скрываем (Visible[Node]:=False). И всё - исходный список не трогается, AbsoluteIndex у нодов не меняется...
нет-нет, у меня ведь "ленивая" загрузка - информация не грузится на клиента. Ответ сервера - общее количество записей и информация по тому десятку, которая попадает на экран. 

Вот и такой момент, что когда клиент начинает вводить свой запрос - общее количество найденных в БД записей постоянно меняется (уменьшается, как правило, но может и увеличиваться), а я в это время изменяю VT.RootNodeCount. Пока смотрится красиво, и даже до пары миллионов записей не тормозит (в реальности их будет на порядки меньше). Но как будет дальше - пока не знаю. 

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)