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

[Android] программа закрывается при использовании LocationSensor и Memo


Rusland

Вопрос

Происходит непонятное явление при определении GPS-координат.

На форме TLocationSensor (LSensor) для получения координат, TMemo (Memo1) для вывода информации и несколько Label (LabLat, LabLon).

Вот такой код 

procedure TForm1.LSensorLocationChanged(Sender: TObject;
  const OldLocation, NewLocation: TLocationCoord2D);
var Lat,Lon:String;
begin
  try
    Lat:=LSensor.Sensor.Latitude.ToString;
    Lon:=LSensor.Sensor.Longitude.ToString;
    LabLat.Text:='Широта:  '+Lat;
    LabLon.Text:='Долгота: '+Lon;
    Memo1.Lines.Add(Lat+';'+Lon);
  finally
  end;
end;

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

 

Кто виноват? Что делать?

Можно ли как-то отловить ошибку и записать, например, в лог-файл (чтобы понять какой компонент виноват)? Если убираю Memo, то программа не закрывается.

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

Рекомендуемые сообщения

  • 0
  • Администраторы

Событие приходит в другом потоке. А с UI можно работать только в главном потоке. Поэтому перед тем, как что-то записывать в мемо, эту запись нужно завернуть в TThread.Synchronize.

procedure TForm17.LocationSensor1LocationChanged(Sender: TObject; const [Ref] OldLocation,
  NewLocation: TLocationCoord2D);
begin
  TThread.Synchronize(procedure
  begin
    Memo1.Lines.Add('');
  end);
end;
Ссылка на комментарий
  • 0

Brovin Yaroslav, не уверен что понял... кто создал тот другой поток, LocationSensor (я то потоков не создаю)? Из-за этого возникает ошибка при обращении к переменным LSensor.Sensor.Latitude и LSensor.Sensor.Longitude ? Тогда как объяснить то что программа работает, если я значения записываю в Label-ы (программа тоже должна рушиться)?

UI? Напомню, что приложение я запускаю на своем телефоне Android (вер.4.2.2)

Ссылка на комментарий
  • 0
  • Администраторы
  1. То что вы не создаете, это не означает, что ваша программа использует всего один поток. Этот сенсор на андроиде работает в другом потоке. Вам нужно понимать только одно, что работать с UI контролами можно только в UI потоке. 
  2. На счет TLabel - вам просто повезло. Это простой контрол. А вот с TMemo, как вы поняли, такое везение не проходит. Так как TMemo вычисляет размеры линий. И если вы в момент вычисления линий, добавляете или удаляете линию, то можно спокойно поймать EArgumentOfRange исключение
Ссылка на комментарий
  • 0

Очень часто вижу реализацию через Мемо напрямую, в частности на этом форуме :) Странно что там у людей работало )

 

 

procedure TForm17.LocationSensor1LocationChanged(Sender: TObject; const [Ref] OldLocation,
  NewLocation: TLocationCoord2D);
begin
  TThread.Synchronize(procedure
  begin
    Memo1.Lines.Add('');
  end);
end;

Объясните пожалуйста как правильно сделать Synchronize? (Выше приведенный код не работает)

 

 

 то можно спокойно поймать EArgumentOfRange исключение

И почему это исключение не вываливается на экран как ошибка, а приложение просто берет и закрывается?

Ссылка на комментарий
  • 0
  • Модераторы
TThread.Synchronize(nil, procedure
begin
  Memo1.Lines.Add('');
end);
И почему это исключение не вываливается на экран как ошибка, а приложение просто берет и закрывается?

 

потому что работает в другом потоке!

Изменено пользователем ZuBy
Ссылка на комментарий
  • 0
procedure TForm17.LocationSensor1LocationChanged(Sender: TObject; const [Ref] OldLocation,
  NewLocation: TLocationCoord2D);
begin
  TThread.Synchronize(procedure
  begin
    Memo1.Lines.Add('');
  end);
end;

А как этот код будет выглядеть в С++ Builder?

Спасибо.

Ссылка на комментарий
  • 0
TThread.Synchronize(nil, procedure
begin
  Memo1.Lines.Add('');
end);

Спасибо. Не вылетает  ;)

 

 

 

Вам нужно понимать только одно, что работать с UI контролами можно только в UI потоке. 

Теперь становится яснее.

C какими еще компонентами кроме Memo надо работать через Synchronize?

 

Какое ограничение на размер строк в Мемо?

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

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

 

ограничения по Memo я поставил 1000 символом и после чего очищаю его (для логов использовал)

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

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

Я вот тоже прикрутил TMapView и в зависимости от показаний LocationSensor ставлю на карте Маркер текущего положения. Поставил Timer и в нем вызываю вот такую процедуру:

 
procedure TForm2.SetMarker();
var Descr: TMapMarkerDescriptor;
    MyLocation: TMapCoordinate;
begin
  TThread.Synchronize(nil, procedure
  begin
    try
      if (TabControl.ActiveTab=TabMap)and((PrevLat<>LSensor.Sensor.Latitude) or (PrevLon<>LSensor.Sensor.Longitude)) then
      begin
        PrevLat:=LSensor.Sensor.Latitude;
        PrevLon:=LSensor.Sensor.Longitude;
        MyLocation:=TMapCoordinate.Create(LSensor.Sensor.Latitude,LSensor.Sensor.Longitude);
        MapView.Location:=MyLocation;
        Descr:=TMapMarkerDescriptor.Create(MyLocation);
        Descr.Draggable:=True;
        if Assigned(MyMarker) then MyMarker.Remove; // удаляю предыдущий маркер
        MyMarker:=MapView.AddMarker(Descr);         // добавляю на карту новый 
      end;
    except
      ShowMessage('Произошла непредвиденная ошибка');
    end;
  end);
end;

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

Во-вторых, если я вызываю эту процедуру прямо из обработчика LocationChanged, то программа зависает. Нельзя слишком часто обращаться к компоненту MapView? Можно ли как-то узнать что в MapView загрузка завершена?

 

Ничего лучше кроме маркера не придумал. Может есть другие варианты указания текущего местоположения?

Есть параметр скорость LSensor.Sensor.Speed - но он показывает что-то странное. При движении 40-50км в час, он показывает 9-10. Как правильно узнать скорость?

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

Если у вас зависает программа, то замените Synchronize на TThread.Queue. Это точно должно помочь

 

Этим летом мне выделили время и я плотно занимался проблемой "черного экрана" на андроиде и креша при закрытии приложения на Андроиде. На форуме было очень много обсуждений этой проблемы. Поэтому есть пара советов, как ее избежать в текущих версия среды:

  1. Все операции требуемые выполнять в Delphi UI потоке нужно выполнять в Synchronize или Queue. Второе предпочтительнее. Отличие между Synchronize и Queue - только в том, что первое остановит выполнение потока до тех пор, пока не выполниться код в SynchronizeQueue наборот, поставить в очередь ваш код на выполнение. Поэтому если вы можете выполнять вашу задачу асинхронно, то лучше использовать Queue, если нет, то Synchronize.

В вашем случае вы можете выполнить добавление маркера асинхронно, так как результат сенсора вы не используете в будущем для вычислений. То есть у вас только задача отображения данных в Real Time. Поэтому 

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

Если у вас зависает программа, то замените Synchronize на TThread.Queue. Это точно должно помочь

 

Этим летом мне выделили время и я плотно занимался проблемой "черного экрана" на андроиде и креша при закрытии приложения на Андроиде. На форуме было очень много обсуждений этой проблемы. Поэтому есть пара советов, как ее избежать в текущих версия среды:

  1. Все операции требуемые выполнять в Delphi UI потоке нужно выполнять в Synchronize или Queue. Второе предпочтительнее. Отличие между Synchronize и Queue - только в том, что первое остановит выполнение потока до тех пор, пока не выполниться код в SynchronizeQueue наборот, поставить в очередь ваш код на выполнение. Поэтому если вы можете выполнять вашу задачу асинхронно, то лучше использовать Queue, если нет, то Synchronize.

В вашем случае вы можете выполнить добавление маркера асинхронно, так как результат сенсора вы не используете в будущем для вычислений. То есть у вас только задача отображения данных в Real Time. Поэтому 

 

Вот спасибо огроменное! Заменил Synchronize на Queue и не зависает теперь при вызове из LocationChanged  :D (не люблю Timer-ы)

 

PS. помогите кто-нибудь Kitty

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

Если у вас зависает программа, то замените Synchronize на TThread.Queue. Это точно должно помочь

 

Этим летом мне выделили время и я плотно занимался проблемой "черного экрана" на андроиде и креша при закрытии приложения на Андроиде. На форуме было очень много обсуждений этой проблемы. Поэтому есть пара советов, как ее избежать в текущих версия среды:

  1. Все операции требуемые выполнять в Delphi UI потоке нужно выполнять в Synchronize или Queue. Второе предпочтительнее. Отличие между Synchronize и Queue - только в том, что первое остановит выполнение потока до тех пор, пока не выполниться код в SynchronizeQueue наборот, поставить в очередь ваш код на выполнение. Поэтому если вы можете выполнять вашу задачу асинхронно, то лучше использовать Queue, если нет, то Synchronize.

В вашем случае вы можете выполнить добавление маркера асинхронно, так как результат сенсора вы не используете в будущем для вычислений. То есть у вас только задача отображения данных в Real Time. Поэтому 

 

Это все конечно хорошо, но не всегда работает.

Вот такая зверская конструкция на Windows отрабатывается на ура, а на андроиде бывают лаги

TTask.Run(procedure 
begin 
  // тут обращение к базе например
  TThread.Synchronize(nil, procedure
  begin
     //  тут разбираем данные
    TTask.Run(procedure 
    begin
      // тут сохраняем
      TThread.Queue(nil, procedure 
      begin
         // тут обновляем данные в визуальных компонентах
      end);
    end);
   end);
end);

пришлось отказаться от такой конструкции, но иногда она жутко удобна

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

Вот такая зверская конструкция на Windows отрабатывается на ура, а на андроиде бывают лаги

 

 

{$IFDEF offtop}Мсье знает толк в извращениях :D {$ENDIF}

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

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

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

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

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

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

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

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

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

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

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