qz5 Опубликовано 14 августа, 2019 Поделиться Опубликовано 14 августа, 2019 Делаю приложение для Андроид, у которого есть база данных на SQLITE, в нем будут сотни и тысячи записей. По нажатию кнопки должен происходить поиск и вывод значений из базы. Сделал так: положил на форму FDConnection, FDQuery, ListView и сделал биндинг значений от FDQuery в айтемы ListView. При нажатии кнопки "Выборка" идет простой Select запрос и приложение "задумывается", т.е. интерфейс полностью останавливается. Сделал в отдельном потоке вот так: TThread.Synchronize(nil, procedure begin FDConnection1.Params.Values['Database'] := PathToDB; FDConnection1.Connected := True; FDQuery1.Active := True; end); но всё равно интерфейс останавливается. Как сделать выборку из базы без фризов интерфейса? Цитата Ссылка на комментарий
0 Сергей Сергеев Опубликовано 15 августа, 2019 Поделиться Опубликовано 15 августа, 2019 Synchronize - синхронизирует с основным потоком, я делал так - получал данные в потоке, без синхронизации, перегружал в видимы контролы в потоке с синхронизацией, а основной поток в это время крутил индикатор.. qz5 1 Цитата Ссылка на комментарий
0 qz5 Опубликовано 16 августа, 2019 Автор Поделиться Опубликовано 16 августа, 2019 В принципе тоже переделал на вариант без биндингов, а добавлять в цикле item и у него выставлять значения полей Цитата Ссылка на комментарий
0 qz5 Опубликовано 16 августа, 2019 Автор Поделиться Опубликовано 16 августа, 2019 пробовал https://stackoverflow.com/questions/37830470/firedac-freezes-gui но мне не помогло, всё равно интерфейс останавливался Цитата Ссылка на комментарий
0 Сергей Сергеев Опубликовано 16 августа, 2019 Поделиться Опубликовано 16 августа, 2019 (изменено) Может данные получаются быстро, а байндятся долго, который через синхронайз. Закоментируйте байдинг данных, останется только получение, и посмотрите что с интерфейсом, не должен фризится если все правильно. Если это так, то у вас "долгий" байндинг в основном потоке через синхронайз.. и Фризит . может переделать как то надо по-другому. Пс. У меня датаснап, через клиентдатасет, но в принципе тот же файрдак. коннект и получение данных в датасет не привязанный к данным в потоке. А в синхронайзе копирование данных из непривязанного ДС в прибайденный визуально к листВью. записей до 50 примерно.. получение через мобильный интернет может занимать 10-20 сек, а байдинг - полсекунды и в этот момент , индикатор, конечно подрагивает. Изменено 16 августа, 2019 пользователем Сергей Сергеев добавил Цитата Ссылка на комментарий
0 Сергей Сергеев Опубликовано 16 августа, 2019 Поделиться Опубликовано 16 августа, 2019 (изменено) вот нашел свой пример, который года три назад тоже подсмотрел гдето.. Спойлер procedure Run(ATask: TProc<TFrameWait>; AOnComplete: TProc<TFrameWait> = nil; AOnError: TProc<TFrameWait, Exception> = nil); virtual; procedure DoErrorHandling(E: Exception; AOnError: TProc<TFrameWait, Exception>); procedure DoOnCompleted(AOnComplete: TProc<TFrameWait>); procedure TFrameWait.Run(ATask, AOnComplete: TProc<TFrameWait>; AOnError: TProc<TFrameWait, Exception>); begin currThread := TThread.CreateAnonymousThread( procedure begin try try FHadErrors := False; ATask(Self); DoOnCompleted(AOnComplete); except on E:Exception do DoErrorHandling(E, AOnError); end; finally end; end); currThread.Start; end; procedure TFrameWait.DoErrorHandling(E: Exception; AOnError: TProc<TFrameWait, Exception>); begin TThread.Synchronize(TThread.CurrentThread, procedure begin FHadErrors := True; if Assigned(AOnError) then AOnError(Self, E); end); end; procedure TFrameWait.DoOnCompleted(AOnComplete: TProc<TFrameWait>); begin TThread.Synchronize(TThread.CurrentThread, procedure begin if Assigned(AOnComplete) then AOnComplete(Self); // Close; end); end; В качестве параметров - фрейм или форма, в которой крутится индикатор и накрывающий приложение полу прозрачностью, чтобы пользователь не тыкал ничего лишнего Есть кнопка - Cancel.. Вызов - такой.. Run( // коннект и выполнение sql - получение ответа procedure(AWaitForm: TFrameWait) begin conn := false; AWaitForm.UpdateProgress(30,'Соединение...'); ClientModuleNew.Connect(FormMain.HostDS,FormMain.port,FormMain.protocol,FormMain.HostP); --- Reply := aClient.GetTelByCart(StrToInt(editNCart.Text)) end, // то что в ДуОнКомплит - уже с синхронайз т.е. поочереди с основным потоком - индикатор тут может подтармажиавть procedure(AWaitForm: TFrameWait) begin if (AWaitForm.HadErrors or AWaitForm.wfFlagCancel) then begin AWaitForm.LayoutBtBackClick(nil) ; Toast( 'Ошибка соединения!'); exit; end; if Reply ='' then Toast('Номер телефона не определен.') else if Reply ='1' then Toast('Смена пароля не реже 1 раз в 10 минут.') else if Reply ='2' then Toast('Первый раз получить пароль только по ФИО!') else begin // все хорошо делаем полезные присвоения end; AWaitForm.LayoutBtBackClick(nil) ; // закрытие формы ( фрейма) end, // то что в он Еррор - тоже через Синхро procedure (AWaitForm: TFrameWait; AException: Exception) begin // ShowMessage( AException.Message); if ((FormMain as TFormMain).FlagToast) then Toast('Error Except: ' + AException.Message) else Toast('Ошибка соединения.') ; AWaitForm.LayoutBtBackClick(nil) ; end ); end; вид формы - фрейма под которой это все происходит , индикатор это TArc - который крутится Анимацией Изменено 16 августа, 2019 пользователем Сергей Сергеев qz5 1 Цитата Ссылка на комментарий
0 qz5 Опубликовано 16 августа, 2019 Автор Поделиться Опубликовано 16 августа, 2019 Спасибо, посмотрю. У меня долго именно байндинг, потому что сделал как тут советуют: https://stackoverflow.com/questions/37830470/firedac-freezes-gui и тогда долго работает именно эта процедура: procedure TQueryThread.TransferData; begin Form.FDQuery1.DisableControls; Form.FDQuery1.Data := Query.Data; Form.FDQuery1.EnableControls; end; причем если закомментировать: Form.FDQuery1.Data := Query.Data; тогда всё быстро. А как раз на FDQuery1 и привязан Лайвбингдинг, как только в нем появляются данные - это занимает кучу времени. Цитата Ссылка на комментарий
0 Сергей Сергеев Опубликовано 16 августа, 2019 Поделиться Опубликовано 16 августа, 2019 (изменено) понятно.. выход один - порциями подкидывать те данные которые видны + 2-3 экрана вперед.. где то тут попадалось обсуждение с "подсосом" данных, по мере скрола листвью.. что то про картинки с сервера.. 1000 -и но это конечно еще те танцы.. может и не так страшно.. показать картинку статитику - Ждите! и кнопку "Назад", присвоение данных сделать циклом и в цикле смотреть - не нажата ли кнопка "Назад" - если нажата - откатить.. пс. а сколько из базы строк ( айтемов) получаете? Изменено 16 августа, 2019 пользователем Сергей Сергеев Цитата Ссылка на комментарий
0 qz5 Опубликовано 16 августа, 2019 Автор Поделиться Опубликовано 16 августа, 2019 Это база данных, с которыми будут работать пользователи. У кого-то 500-700, у кого 30-50, а у кого-то может и десятки тысяч (такое возможно). Короче решил сделать вообще без лайвбиндинга, а просто запрашивать данные, потом например по 1000 создавать Item в ListView, а если хочет дальше, то просто с помощью пагинации, а не бесконечной прокруткой. Цитата Ссылка на комментарий
0 qz5 Опубликовано 16 августа, 2019 Автор Поделиться Опубликовано 16 августа, 2019 Но вот прямо сейчас у меня из базы прихходит около 400 записей Цитата Ссылка на комментарий
0 #WAMACO Опубликовано 16 августа, 2019 Поделиться Опубликовано 16 августа, 2019 Странно, у меня 12 тыщ справочник. Получаю по DataSnap (около 15 секунд, в фоне, для пользователя не заметно), потом в ListView для выбора в форму (3-4 секунды). Везде кручу индикаторы, всем кажется что быстро все. Сначала делал на скрытую форму, но потом случайно реализовал на уже показанную, открытую форму и.... какое было мое удивление, что это работает в 100 раз быстрее.... не знаю в чем дело, но Ярослав как то говорил, что FMX использует как-то видимый канвас для вывода.... Цитата Ссылка на комментарий
0 qz5 Опубликовано 17 августа, 2019 Автор Поделиться Опубликовано 17 августа, 2019 Долго делается только когда используется Лайвбиндинг, если его убирать - всё делается мгновенно Цитата Ссылка на комментарий
0 Сергей Сергеев Опубликовано 17 августа, 2019 Поделиться Опубликовано 17 августа, 2019 В смысле убрать? Вообще не отображать? Или байднить в ручную циклом? Конечно быстро, если не показывать, а в оп сложить.. я так и не понял, вы выбираете в один датасет, а потом перегружаете в другой? Который прибайден... Цитата Ссылка на комментарий
0 qz5 Опубликовано 17 августа, 2019 Автор Поделиться Опубликовано 17 августа, 2019 У меня используется только один FDConnection и один FDQuery. В FDQuery идет Select запрос из базы, а от FDQuery уже байндится на ListView вот если так оставить, то при запросе - всё тормозится на несколько секунд и может выводиться сообщение, что "приложение не отвечает" а если убрать байндинг - всё быстро пока сделал так: байндинг убрал, а вместо него в цикле обрабатывают результаты запроса и добавляю ListItem, причем после каждого добавления выполняю application.processmessages Ingalime 1 Цитата Ссылка на комментарий
0 krapotkin Опубликовано 17 августа, 2019 Поделиться Опубликовано 17 августа, 2019 processmessages на андроид зачем??? почему нельзя в потоке открыть и зафетчить записи, а уже потом добавить binding Tumaso 1 Цитата Ссылка на комментарий
0 qz5 Опубликовано 17 августа, 2019 Автор Поделиться Опубликовано 17 августа, 2019 а что, application.processmessages в Андроиде не работает? 31 минуту назад, krapotkin сказал: почему нельзя в потоке открыть и зафетчить записи, а уже потом добавить binding возможно попробую, но как это сделать? Цитата Ссылка на комментарий
0 krapotkin Опубликовано 17 августа, 2019 Поделиться Опубликовано 17 августа, 2019 ну как у вас binding приявязан сейчас ? отвяжите. потом привяжете обратно Цитата Ссылка на комментарий
0 qz5 Опубликовано 17 августа, 2019 Автор Поделиться Опубликовано 17 августа, 2019 Не разобрался как это делать программно Цитата Ссылка на комментарий
0 Сергей Сергеев Опубликовано 19 августа, 2019 Поделиться Опубликовано 19 августа, 2019 (изменено) я тоже не разобрался.. т.к. у меня в дизайнере создана custom item, все в Live Binding настроено.. поэтому ( для моего случая подходит - т.к. данных немного , не боле 100).. создал два одинаковых DataSet - один это результат запроса, никуда не приделан, второй ( полученный копированием в дизайнере первого) - прибайденный. Открываю запрос - заполняется первый датасет ( это в потоке без синхронайза, т.к. на экран ничего не выводится), на экране нет еще данных. Копирую из 1го во второй - и данные на экране появляются( это уже в синхронайзе). Это позволило развязать получение данных с сервера и отображение их на экране. Понятно, что данных в два раза больше, но для меня не критично. Изменено 19 августа, 2019 пользователем Сергей Сергеев qz5 и Ingalime 2 Цитата Ссылка на комментарий
0 qz5 Опубликовано 20 августа, 2019 Автор Поделиться Опубликовано 20 августа, 2019 Понятно, я пробовал вроде похожий метод взятый отсюда: https://stackoverflow.com/questions/37830470/firedac-freezes-gui всё равно не удовлетворило Сергей Сергеев 1 Цитата Ссылка на комментарий
Вопрос
qz5
Делаю приложение для Андроид, у которого есть база данных на SQLITE, в нем будут сотни и тысячи записей.
По нажатию кнопки должен происходить поиск и вывод значений из базы.
Сделал так: положил на форму FDConnection, FDQuery, ListView и сделал биндинг значений от FDQuery в айтемы ListView.
При нажатии кнопки "Выборка" идет простой Select запрос и приложение "задумывается", т.е. интерфейс полностью останавливается.
Сделал в отдельном потоке вот так:
но всё равно интерфейс останавливается.
Как сделать выборку из базы без фризов интерфейса?
Ссылка на комментарий
19 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.