Перейти к содержанию
Fire Monkey от А до Я
  • 0

LiveBinding на ListView и FireDAC в отдельном потоке без "заморозки" интерфейса на Андроид?


qz5

Вопрос

Делаю приложение для Андроид, у которого есть база данных на 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

Synchronize - синхронизирует с основным потоком, я делал так - получал данные в потоке, без синхронизации, перегружал в видимы контролы в потоке с синхронизацией, а основной поток в это время крутил индикатор..

Ссылка на комментарий
  • 0

Может данные получаются быстро, а байндятся долго, который через синхронайз. Закоментируйте байдинг данных, останется только получение, и посмотрите что с интерфейсом, не должен фризится если все правильно. Если это так, то у вас "долгий" байндинг в основном потоке через синхронайз.. и Фризит . может переделать как то надо по-другому. 

Пс. У меня датаснап, через клиентдатасет, но в принципе тот же файрдак. коннект и получение данных в датасет не привязанный к данным в потоке. А в синхронайзе копирование данных из непривязанного ДС в прибайденный визуально к листВью. записей до 50 примерно..   получение через мобильный интернет может занимать 10-20 сек, а байдинг - полсекунды и в этот момент , индикатор, конечно подрагивает.

Изменено пользователем Сергей Сергеев
добавил
Ссылка на комментарий
  • 0

вот нашел свой пример, который года три назад тоже подсмотрел гдето..

Спойлер



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 - который крутится Анимацией

image.png.00e628489fc99d39a8761d7d4c2726d4.png

 

 

Изменено пользователем Сергей Сергеев
Ссылка на комментарий
  • 0

Спасибо, посмотрю.

У меня долго именно байндинг, потому что сделал как тут советуют: 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

понятно.. выход один - порциями подкидывать те данные которые видны + 2-3 экрана вперед.. где то тут попадалось обсуждение с "подсосом" данных, по мере скрола листвью.. что то про картинки с сервера.. 1000 -и

но это конечно еще те танцы.. может и не так страшно.. показать картинку статитику - Ждите! и кнопку "Назад", присвоение данных сделать циклом и в цикле смотреть - не нажата ли кнопка "Назад" - если нажата - откатить..

пс. а сколько из базы строк ( айтемов) получаете?

Изменено пользователем Сергей Сергеев
Ссылка на комментарий
  • 0

Это база данных, с которыми будут работать пользователи. У кого-то 500-700, у кого 30-50, а у кого-то может и десятки тысяч (такое возможно).

Короче решил сделать вообще без лайвбиндинга, а просто запрашивать данные, потом например по 1000 создавать Item в ListView, а если хочет дальше, то просто с помощью пагинации, а не бесконечной прокруткой.

Ссылка на комментарий
  • 0

Странно, у меня 12 тыщ справочник. Получаю по DataSnap (около 15 секунд, в фоне, для пользователя не заметно), потом в ListView для выбора в форму (3-4 секунды).

Везде кручу индикаторы, всем кажется что быстро все. Сначала делал на скрытую форму, но потом случайно реализовал на уже показанную, открытую форму и.... какое было мое удивление, что это работает в 100 раз быстрее.... не знаю в чем дело, но Ярослав как то говорил, что FMX использует как-то видимый канвас для вывода.... 

Ссылка на комментарий
  • 0

В смысле убрать? Вообще не отображать? Или байднить в ручную циклом? Конечно быстро, если не показывать, а в оп сложить..  я так и не понял, вы выбираете в один датасет, а потом перегружаете в другой? Который прибайден...

Ссылка на комментарий
  • 0

У меня используется только один FDConnection и один FDQuery. В FDQuery идет Select запрос из базы, а от FDQuery уже байндится на ListView

вот если так оставить, то при запросе - всё тормозится на несколько секунд и может выводиться сообщение, что "приложение не отвечает"

а если убрать байндинг - всё быстро

пока сделал так: байндинг убрал, а вместо него в цикле обрабатывают результаты запроса и добавляю ListItem, причем после каждого добавления выполняю application.processmessages

Ссылка на комментарий
  • 0

а что, application.processmessages в Андроиде не работает?

 

31 минуту назад, krapotkin сказал:

почему нельзя в потоке открыть и зафетчить записи, а уже потом добавить binding 

возможно попробую, но как это сделать?

Ссылка на комментарий
  • 0

я тоже не разобрался.. т.к. у меня в дизайнере создана custom item, все в Live Binding настроено.. поэтому ( для моего случая подходит - т.к. данных немного , не боле 100).. создал два одинаковых DataSet - один это результат запроса, никуда не приделан, второй ( полученный копированием в дизайнере первого) - прибайденный.  Открываю запрос - заполняется первый датасет ( это в потоке без синхронайза, т.к. на экран ничего не выводится), на экране нет еще данных. Копирую из 1го во второй - и данные на экране появляются( это уже в синхронайзе). Это позволило развязать получение данных с сервера и отображение их на экране. Понятно, что данных в два раза больше, но для меня не критично.

Изменено пользователем Сергей Сергеев
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...