Пользователь
0,0
рейтинг
20 декабря 2013 в 14:37

Разработка → Delphi XE5 + Android: первые впечатления из песочницы

Возвращение к истокам


Delphi XE5 я взял в руки по случаю конкурса «Осенняя Мобилизация». Идея (и возможность) писать под Андроид не на си-шарпе или яве, а на знакомом вдоль и поперёк паскале мне определённо понравилась. Расскажу тут о своих впечатления, проблемах, которые встретились, а также развенчаю некоторые «городские легенды».

Использовал триал-версию Update-1. Теперь уже вроде второй апдейт вышел и, возможно, что-то поменялось. Сразу замечу, что менять в установке настройки по умолчанию лучше не стоит. Установленный до этого Андроид-SDK прицепить к Делфи не удалось, поэтому ставил заново с тем, который к ней прилагается. После первого запуска выяснилось, что не работает Хелп. Нашёл решение
support.embarcadero.com/article/43035

Хелп оказался толковый и довольно подробный. Содержит не только свойства и методы, но и примеры и даже описание методик разработки. В общем, возвращение к истокам, как оно было ещё у Борланда.

Cама среда мне очень нравится. В Визуал Студио всё какое-то аморфное и невнятное. Юнити визуально неплох, но там совсем другая специфика. Короче – язык программиста всё равно не опишет то, что видит глаз эстета, даже если они принадлежат одному человеку…

Интерфейс пользователя

FireMonkey порадовал своей гибкостью. На любой контрол можно повесить другой, на тот ещё один, и так далее, достигая очень интересных результатов. По сравнению с VCL стандартизовано именование свойств. Никаких больше Caption’ов и прочего, если где-то есть текст – это всегда Text. Позиция – всегда Position. Масса способов выравнивания. Кроме того, есть TLayout – нечто «невещественное» (об этом будет и ниже), невидимое, на что можно положить контролы и выравнивать их «в пустоте», а не обязательно на какой-нибудь панели.

Когда много всего на форме, становится очень полезным свойство DesignVisible – скрыть в дизайн-тайме. Набор стилей для Андроида прилагался только один, но очень элегантный – белым по чёрному, как мне нравится.
В инете ходят слухи, что ссылки на стиль для контрола (StyleLookup) иногда «не сохраняются». Для многих типов контролов (а может и для всех) существует для каждого своя ссылка «по умолчанию», которая будет назначена, даже если не указана, и которая-то и не сохраняется, как я понимаю, для экономии места в ресурсе формы.

Контролу можно добавить анимацию, и даже несколько, и даже одновременно. И это не только перемещение по экрану, но и изменение любых вещественно-численных свойств (размеров, цвета, масштаба и т.д.). Для каждой анимации можно указать временную задержку её начала, что очень удобно в сложных случаях, т.к. можно обойтись без дополнительных таймеров, просто запустив все нужные анимации одновременно из одного блока кода.

Теперь о жестах. В принципе всё просто – назначаем контролу Touch.GestureManager, галочками помечаем интересующие жесты, назначаем искусственное расширение границ ловли жестов (если контрол мелкий) в TouchTargetExpantion, создаём для него событие OnGesture и ловим там по EventInfo.GestureID нужный жест. Но есть тонкости.

Например, на большом TLayout мы разместили какие-то мелкие (относительно него) контролы и независимо от того, насколько «попал» пользователь пальцем по этим контролам своим жестом, надо что-то там делать. Замечу – если всё описанное в абзаце выше сделано для этого TLayout, то мы поймаем только те жесты, начало которых приходится на «видимые» объекты – т.е. на один из тех самых мелких контролов. Это я определил экспериментально. В принципе ничего удивительного – лайоута-то как бы и нет, он невидим и виртуален, и все «экранные сообщения», которые он может получить – от положенных на него «видимых» объектов. Можно сделать по-другому — не лениться, назначить менеджера и создать событие для формы (как и делается в демках) и гарантированно его всегда получать – но тогда придётся вручную разбираться с координатами, чтобы определить, к какому контролу какой жест относится.

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

И пример. Долго не мог сообразить, как показать баннер в TWebBrowser. Решение нашёл на одном форуме и творчески переработал. Но, если быть уж совсем точным, не до конца. Практикующие перфекционисты могут поразвлечься и этот недочёт поискать. Однако код при этом абсолютно рабочий и именно его я использую:

procedure ShowHtml(WebBrowser: TWebBrowser; const Html: string);
{$IF DEFINED(ANDROID)}
const
  tempFile: string = '/sdcard/Download/temp.htm';
  filePrefix: string = 'file:/';
var
  StrList: TStringList;
  MemStrem: TMemoryStream;
begin
  with WebBrowser do
  try
    StrList := TStringList.Create;
    StrList.Text := Html;
    StrList.SaveToFile(tempFile);
    URL := '';
    Navigate(filePrefix + tempFile);
  finally
    DeleteFile(filePrefix + tempFile);
    StrList.Free;
  end;
{$ELSE}
begin
{$ENDIF}
end;

HTML тут – это код этого самого банера.

Базы данных


В XE5 включён набор компонентов для универсального доступа к базам данных – FireDAC. В принципе все названия свойств и методов как у других аналогичных наборов, так что тут всё ясно. Я использовал его для общения с SQLite. Всё настолько просто и обычно, что даже не знаю, что рассказать. К тому же и не помню ничего – в это время смотрел что-то по медиаплейеру, руки сами всё сделали.

Чтобы почувствовать разницу, желающие могут для сравнения после FireDAC сделать что-нибудь с базой данных из программы на той же Юнити. Да ладно Юнити, она игровая, – вон из той же Визуал Студии. После этого начинаешь понимать, где пули свистят, а где туземки коктейли разносят…

Ну и для любителей делать всё своими руками приведу небольшой пример, как заполнять ListBox без Bindings:

procedure TSomeForm.FillList(aList: TListBox; BegDate, EndDate: TDateTime);
var
  aItem: TListBoxItem;
begin
  aList.Items.Clear;
  with SomeQuery do
  try
    ParamByName('beg_date').AsDateTime := BegDate;
    ParamByName('end_date').AsDateTime := EndDate;
    Open;
    while not EOF do
    begin
      aItem := TListBoxItem.Create(aList);
      aItem.StyleLookup := 'listboxitemrightdetail';
      aItem.Tag := FieldByName('id').AsInteger;
      aItem.Text := Format('%s (%s) "%s"',
        [FieldByName('theme').AsString,
        FieldByName('name').AsString,
        FieldByName('question').AsString]);
      case FieldByName('d_result').AsInteger of
        -1: aItem.ItemData.Bitmap.Assign(NoImage.Bitmap);
         0: aItem.ItemData.Bitmap.Assign(WaitImage.Bitmap);
         1: aItem.ItemData.Bitmap.Assign(YesImage.Bitmap);
      end;
      aItem.ItemData.Detail := FormatDateTime('dd-mmm-yy', FieldByName('d_date').AsDateTime);
      aItem.ItemData.Accessory := TListBoxItemData.TAccessory.aMore;
      aList.AddObject(aItem);
      Next;
    end;
  finally
    Close;
  end;
end;


Кроме всего прочего, в зависимости от кода в столбце d_result в строчку лист-бокса помещается та или иная картинка:

aItem.ItemData.Bitmap.Assign

Главное, что тут не забыть – это aList.AddObject(aItem);

Ну и Next, конечно, чтобы не зависло.

Манипуляции с формами


То, к чему приучает Делфи – это каждому действию свою форму. Под Андроидом в ней можно точно так же, как и под Виндоуз, создавать, показывать и закрывать формы. Каждая новая так или иначе созданная и показанная форма будет как бы «модальной», т.е. закрывающей всё пространство приложения. Однако Form.ShowModal делать не следует (Андроид этого «не понимает»), а следует по старинке просто вызывать Form.Show. По системной кнопке Back автоматом вызывается Form.Close и самая верхняя на данный момент форма закрывается. Можно её потом опять использовать. При закрытии главной (первой) формы приложение, как и следовало ожидать, закрывается. Замечу, что не следует закрывать форму с параметром caFree либо явно её уничтожать (Free, Release) – не любит Андроид этого!

Подсчёт ссылок.

Читал в инете про проблемы у людей с ARC. Уверен, дело не в этом. Если всё правильно спроектировано, то вообще без разницы, считаются ссылки или нет, ходит там сборщик мусора с косой по расписанию как в .Net или уничтожается сразу как в Delphi. Я всё писал по-старинке:

try
  Create;
finally
  Free;
end


и работало как часы и под Андроидом, и под Виндами.

Если же возникают какие-либо проблемы с пониманием этого процесса, без всякого стёба рекомендую немного пописать на си-шарпе. Там вообще деструкторы явно вызывать не принято, просто или выходишь из процедуры, где данный объект был локальной переменной, или присваиваешь (глобальной) переменной значение null. Через некоторое время уже спинным мозгом начинаешь чувствовать момент, когда ладьи с объектами отправляются в Вальгаллу, причём безо всякого с твоей стороны толчка.

Массивы


При разработке под мобильный компилятор в руководстве по адаптации кода сказано «не использовать статические массивы». Указано также одно исключение – когда статический массив является членом структуры. И всё. Не совсем ясно, относится ли это к константам-массивам. Например, таким как

Const
SomeNames: array [0..1] of string = (‘First’, ‘Last’);


Не исключено, что так делать можно, хотя я такого старался избегать и формировал массивы строк в initialization динамически. В си-шарпе там хоть это можно в описании делать… Короче, вопрос требует дальнейшего исследования и разъяснения.
Следует также помнить, что элементы строки (string) в мобильном компиляторе нумеруются с нуля.

Операторы


Появился (уж не знаю в какой версии) новый оператор

for item in container do

Похоже, все языки стремятся к общему знаменателю. Кстати, перебирать им в паскале можно не только массивы, но и множества.

Вопросы и ценные замечания приветствуются.
@amQuests
карма
6,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (73)

  • +2
    Собственно, интересны ваши впечатления от запуска такого приложения на устройстве.
    • –5
      А чем такое приложение должно отличаться от любого другого?
      • +8
        весом?)
      • +8
        Скоростью работы?
      • +3
        Требованиями к версии ОС и устройству?
        • –1
          А вот вы не правы. Приложение, написанное в XE5, прекрасно работает на Galaxy Tab первой модели под Android 2.3 и 2.2 (старее я просто уже не нашёл).
          • +4
            В чем я не прав? Я не утверждал, что оно там не работает. Наоборот, мне интересно узнать, где оно работает, а где нет.
            Вот тут (http://docwiki.embarcadero.com/RADStudio/XE5/en/FireMonkey_Platform_Prerequisites) написано:
            RAD Studio supports the development of applications for Android devices running on an ARMv7 processor with NEON support.
        • +3
          Вот официальный список поддерживаемых устройств
          docwiki.embarcadero.com/RADStudio/XE5/en/Android_Devices_Supported_for_Application_Development#Results_of_Our_Android_Device_Testing
          Вот ещё статья про это
          www.tdelphiblog.com/2013/10/sovmestimostjandroididelphi.html
          • +4
            Спасибо. Вот эта статистика снимает все вопросы:

            Проверено устройств: 118
            Не установилось на: 10
            Зависло (Application not responding) на: 3
            Успешно запустилось на: 105
            Процент успеха: 89%

            Но там проверяли Hello World, на более сложных приложениях проблем будет, очевидно, больше.
            • +4
              Уверен, что реально работает практически на всём. Поясню почему.
              Использовались, судя по всему, не тесты, а кривые «антитесты». Почитал про свой аппарат:

              Samsung Galaxy Tab2 10 Bug reported about Location Demo and Audio Recording

              Обиделся. Это же не клон какой-то, это наоборот то, с чего все клоны и делаются. Я его специально для разработки брал, чтобы был самый что ни есть стандартный.

              Посмотрел Location Demo. Запустил. Действительно, показывает, что я в Канзасе. Видимо, и Тотошка с Железным Дровосеком где-то рядом. А долгота-широта-то сверху на лейблах — правильные!

              Смотрим текст. В Гугл-мап строку передаются координаты, полученные через ToString. В России, я так понимаю, будут они с десятичными запятыми. Ищем 1 мин и находим, как надо эту строку формировать:

              support.google.com/maps/answer/18539?hl=ru

              Прямо сказано, что через точку. А цепкому глазу к тому же видно, что после точки — 5 знаков. Не 6, не 123, а пять! Переписываем процедуру из демки:

              procedure TLocationForm.LocationSensor1LocationChanged(Sender: TObject;
                const OldLocation, NewLocation: TLocationCoord2D);
              const
                LGoogleMapsURL: String = 'https://maps.google.com/maps?q=%s,%s&output=embed';
              var
                latS, lonS: string;
              begin
                { convert the location to latitude and longitude }
                Str(NewLocation.Latitude:8:5, latS);
                Str(NewLocation.Longitude:8:5, lonS);
                lbLatitude.Text := 'Latitude: ' + NewLocation.Latitude.ToString;
                lbLongitude.Text := 'Longitude: ' + NewLocation.Longitude.ToString;
              
                { and track the location via Google Maps }
              //  WebBrowser1.Navigate(Format(LGoogleMapsURL, [NewLocation.Latitude.ToString, NewLocation.Longitude.ToString]));
                WebBrowser1.Navigate(Format(LGoogleMapsURL, [latS, lonS]));
              end;
              
              


              Запускаем. Показывает улицу, дом. Чуть ли не квартиру. Всё правильно.

              Я вот сижу и думаю — а сколько в Эмбаркадеро писателям тестов платят, может, устроиться? И сразу всё на всём заработает как часы…
              • +1
                Через это проходят все пользователи их продуктов. Я таким образом менеджер пакетов для Дельфы сделал. Штатные средства — это ужас.
      • –1
        Если про отличия от десктопного приложения — то в первую очередь дизайном интерфейса (ну, понятно, один палец для работы, никаких всплывающих меню и т.п.). А по памяти и быстродействию гаджеты уже догоняют десктопы. Вот у меня на Tab-2 — 1 Gb ОЗУ. Даже неизвестно, чем его можно израсходовать — программа моя ела, я смотрел, лишь 70 Mb. Быстродействие, конечно, пока сильно отстаёт, ну, так не нагружать слишком!
        • 0
          Вы правда думаете что в распоряжении вашей программы весь гигабайт?

          Кстати, а что делает ваша программа? 70 Мб это довольно много даже на десктопе.
          • 0
            Это симулятор гадания на картах. Там множество картинок загружается, и ни на качестве их, ни на размере я не экономил.
    • +1
      Если запускать напрямую с устройства готовую Release сборку, всё работает очень быстро. Я вообще никаких задержек не заметил. Единственно, запуск занимает 3-4 сек, и при этом чёрный экран. Кажется, что долго. Для сравнения запустил Маркет. Те же 4 сек. Только он сразу показывает верхнюю панель и выставляет крутящийся курсор ожидания, потому кажется, что запустился мигом. Вообще надо было бы какой-нибудь сплеш сделать, да времени не хватило.

      Резюмируя — задержек при работе нет, и надо обязательно делать сплеш, чтобы не светить чёрный экран при запуске. Как сделать — вроде на каком-то форуме про это видел, надо опять поискать.
      • 0
        Может быть Вы об этом?
        • 0
          О, тут вообще исчерпывающе про этот вопрос! Нет, где-то на Эмбаркадеровском форуме для разработчиков просто обсуждалось про загрузку картинки в новом потоке, пока приложение стартует — я про это писал. Теперь же материала для размышлений стало гораздо больше. Спасибо.
  • +1
    Столько лишних операторов, на Java Будет и быстрее и лучше.
  • +2
    Чую набегут делфи-хейтеры и заминусуют всё и вся. Я например рад, что можно разрабатывать под андроид на любимом делфи, и судя по отзывам, с производительностью всё нормально.
    • +5
      Вопрос только в том, сколько стоит «любимое делфи» и зачем его покупать, есть на джаве все сделать проще и быстрее?
      • 0
        Вы об этом своем вопросе вспомните, когда захотите свое «быстро и легко сделанное на джаве» приложение перенести на iOS и вдруг окажется, что нужно все начинать с нуля.
        • +1
          Я вас скажу по секрету, что переписать логику с нуля с джавы на шарп стоило сопоставимо покупки лицензии на делфи. Иногда лучше начать с нуля.
          • 0
            Полторы тысячи долларов? Меньше месяца работы квалифицированного программиста? Что же у вас там за приложение такое?
            • +3
              Вот оригинал, а вот порт на айос Спортировать джаву на шарп не составляет особого труда.
              • 0
                Это замечательно, но существуют приложения со стоимостью разработки намного превышающей $1500. Думаю, вы не станете спорить.
                • 0
                  Да и Преферанс затянул намного больше, я только указал сумму, в которую обошлось портирование логики. Самое интересное — это отладка на реальном железе.
        • +3
          Мне кажется, корректней будет Delphi сравнивать с Xamarin. По цене и возможностям, если я правильно вижу, они похожи.
          • +3
            Конечно корректнее. Я, собственно, и не понимаю как можно сравнивать кроссплатформенные средства с сугубо нативными.
      • +1
        В целом, есть ниши, где проще купить делфи за 1500 долларов, чем нанимать толпу специалистов по разным платформам, управлять этой толпой и ежемесячно платить зарплату.
        • +2
          Это если у вас есть дефли специалисты и вы уверены в том, что стоит инвестировать в делфи.
          • –1
            Даже если их нет. Дешевле нанять одного делфи-специалиста и купить ему Delphi, чем нанять двух программистов (Android+iOS). Delphi покупается один раз (ну или раз в N лет, если обновления покупать), а «лишнему» программисту нужно каждый месяц зарплату платить.

            Нет, конечно часто бывают ситуации, когда человек может в одиночку разрабатывать приложения на всех платформах и даже успевать все делать в срок. Но подобные примеры не релевантны, Delphi позиционируется как платформа для бизнес-приложений, а не для еще одних крестиков-ноликов.
            • +2
              Если надо писать хорошее приложение на маркет, то надо делать две отдельные версии для IOS и Android, если писать игру, то можно на юнити написать кросплатформ.

              Написать на Делфи, теоретически можно что то с кнопочками для внутреннего пользования, владельцы айфонов на такое не клюнут.
              • 0
                С ценой разобрались, теперь претензии к кнопочкам? Какие конкретно претензии к кнопочкам, если не секрет?

                Я повторюсь, Delphi позиционируется как платформа для бизнес-приложений. А в этой среде умеют и любят считать деньги — душевные метания хипстеров им мало интересны. Так что не волнуйтесь, разработчики на Delphi врядли будут конкурировать с вашим преферансом для аппстора.

                Но волноваться придется тогда, когда (например) владелец охранного предприятия захочет автоматизировать рабочие места выездных сотрудников и увидит, что вашем исполнении разработка софта обойдется в несколько раз дороже, чем в исполнении команд, использующих кроссплатформенные средства разработки. Он безусловно с интересом выслушает рассказ про Java и кнопочки :)

                А спрос на кроссплатформенность безусловно есть. Так как Delphi далеко не единственный и совсем не самый дорогой подобный инструмент.

                P.S. Если уж вам так хочется отстоять игры, я даже отдельно специально для вас скажу — не надо делать на Delphi игры :)
                • 0
                  А я вот не троллинга ради а интереса для хочу спросить: а вот делфи пока под мобайл не было, бизнес-приложений на айпадах тоже не было?
                  • +1
                    Были конечно. Но мобильные приложения в бизнес-среду медленно просачиваются, там все еще поле не паханное. Сейчас спрос похоже растет, не спроста ведь именно в последние пару лет так много кроссплатформенных средств разработки стало появляться. Delphi лишь одно из них. Вы похоже считаете, что все вокруг заблуждаются — и Embarcadero, и Xamarin, и Adobe, и многие-многие другие.
                    • 0
                      Я не считаю что заблуждаются, более того я всецело за кроссплатформ там где это можно. Просто опять же имхо, есть смысл сделать логику на сервере, а клиенту дать нативный интерфейс, к которому он привык.
                • +1
                  Я тут Java не пользовался, но в студии вполне за 4 дня накидал бизнес приложение… с геолокацией, картой, чтением QR кодов, ну в общем все как по последней моде и нативненько… Хотя конечно до этого 3 дня репу чесал к чему подступиться… :)) До этого Objective C кусал, ничего докусался, таки интегрировал в мармелад GPUImage, да написал пару фишек и заменил модуль звука мармелада с ихнего на свой нативненький так сказать, работало лучше в разы. Но с объективом возился дольше намного. больше сложно синтаксис осилить не взорвав мозг. Зато теперь рад, что могу продолжаь изучение Java и Objective C.
            • +1
              Дешевле нанять C# программиста и купить ему лицензию на Xamarin. И лучше выйдет и платформа гораздо стабильней чем Делфи.
              • +1
                У Xamarin ещё одно преимущество — он сам кроссфплатформенный.
        • +3
          Изучил Ваш блог и нашел 2 весьма интересных поста.

          Первый пост — про разницу в реализации модальных форм на десктопе и мобильных девайсах. Да, в Android при запуске каждого окна старое не ожидает, пока новое закроется. Но ведь и колбеки не используются, потому что Android может в любой момент закрыть предыдущие окна, даже если они ожидают результата от других окон. Все компоненты действительно разделены и при необходимости будут убираться из памяти. В случае же Delphi в памяти будут висеть все предыдущие окна, так как они получают результаты в виде колбека, в котором могут модифицироваться элементы окна, где этот колбек был создан. Если уж стандартное поведение Андроида не используется, не проще было бы в собственной графической песочнице эмулировать привычное дельфистам поведение? Не говоря уже, что так лучше для кроссплатформенности.

          Второй пост — про то что линии с одинаковой толщиной рисуются в Delphi по разному. В нашем Преферансе достаточно серьезно используется Canvas из Android SDK и такая проблема неведома. Координаты и размеры линий задается в числах с плавающей точкой и выглядят на экране сглажено и одинаково. Можете посмотреть на скриншоты пули в Android-версии преферанса. С градиентами и изогнутыми линиями. Мне страшно представить, каких бы усилий стоило бы нарисовать такое в Delphi.

          Возникает вопрос — а не проще ли использовать нативный и предсказуемый инструмент, чем искать, как обходить баги вот в таком вот «кроссплатформенном»? Я уж не представляю, что будет, когда придется искать какую-то платформозависимую багу.

          Еще вопрос, почему такой довольно взрослой и недешевой среде для каждой новой версии требуются патчи от некоего Andreas Hausladen? Неужели в такой бизнес-ориентированной компании как Embarcadero не могут нанять квалифицированный QA отдел и программистов, которые имея полный исходный код фиксили бы те баги, которые один скромный программист фиксит, имея лишь дизассемблер?

          Кстати, по блогам и форумам пишут, что на FireMonkey нету контрола для отображения HTML. Врут? В Android и iOS SDK такие есть.
          • 0
            Про работу с окнами на Android… я сам не очень понял почему они сделали все так, как сделали. Про это и был тот пост в общем :)

            В целом же программ без багов не бывает. Тем более в таких молодых (Android всего-то в сентябре зарелизили). Постепенно стабильность появится, а багов будет меньше. Некоторая сырость — это общий бич кроссплатформенных средств на данный момент. Они все еще молоды.

            P.S. Про HTML врут. Когда-то его не было, но сейчас есть.
          • 0
            Говоря про бизнес, я имел ввиду только то, что у них иные приоритеты. Они вполне будут готовы простить неидеальную прорисовку, если это даст экономию по деньгам или времени.
            • +1
              Опять же, бизнес бизнесу рознь. Тот же клиент для онлайн банкинга должен выглядеть супер и быть понятным пользователю устройства. Можно, к примеру, написать кроссплатформ клиент, но клиентам это не понравится. В этом случае лучше написать два отдельных приложения, чтобы клиенты не разбежались.
      • +2
        А вот хочется писать на любимом делфи. А на нелюбимой яве — не хочется.
        • +1
          Отлично, каждый пишет на том, что ему больше нравится. А там уже будет рынок решать что выгоднее.
          • –1
            А разве сейчас не так?
  • +2
    Спасибо за информацию. Всё никак не соберусь посмотреть на последние версии Дельфи, хотя пишу на нем уже много лет. С появлением поддержки Android думал уже пересесть на ХЕ5, но прочел довольно много критических обзоров — мол, совсем сырая эта поддержка. Как по Вашим ощущениям, можно что-то серьезное написать, или баловство всё это?
    • +2
      Ну по моим ( я не автор статьи, но пробывал ) ощущениям хорошее приложение, занимающее топы вы врятли напишете, но вот специфическое ПО — вполне. Например можно организовать работу выездных специалистов с планшетом. Банальные примеры: инвентаризация на складе, учет техники, техосмотр с занесением всего в журнал. Быстро создать такое приложение вполне возможно. Да и не только такое. Чисто на производстве для внутренних корпоративных целей очень даже подходит, особенно если уже есть специалисты по делфи, а обычно в этом сегменте их есть у них.
    • +1
      Я тоже читал подобные отзывы (сырая и т.п.). Пост и посвящен в том числе развенчанию некоторых таких легенд. 3D я, например, использовать не стал, да для этого есть та же Юнити с тесселяциями и скелетными анимациями.

      А вот что-то «обычное» — панели, кнопки, списки, сетки — это вполне можно делать на Делфи. Если там ещё с базой надо общаться — тогда именно на Делфи (а на чём же ещё?!). Она всегда была именно под это и заточена.

      Надеюсь, с конкурса чего-нибудь опубликуют для всеобщего обозрения, вот и посмотрим, что там и насколько серьёзное получилось. У меня-то программа несерьёзная выложена, но красивая. Анимации, звуки и прочее (в 2D).

      Будет интересно посмотреть, что у кого получилось.
  • 0
    Спасибо, пишите еще.
  • +1
    Меня больше всего интересует производительность FMX. Последний раз я пробовал работать с FM на Delphi XE3, и производительность меня очень не порадовала. Мне всего-то нужен был примерно такой список:
    Картинко

    Само собой элементы списка должны уметь динамически меняться. На них появляются прогрессбары, в момент загрузки, статус загрузки и т.п. иногда на них анимация может крутиться.
    Я реализовал этот список. Закинул в него около 150-200 элементов, и оно стало заметно подтормаживать, особенно заметно на скроллинге. И это всего лишь один список. Для меня это оказалось не приемлемо, ибо у меня машина не самая слабая, а приложение я хотел очень легкое, шустрое и отзывчивое. Подобные списки с тысячами элементов, сортировками, поисками и всем чем только можно — я прекрасно реализую на TVirtualTreeView, и оно на VTV работает на порядки шустрее с десятками тысяч — чем этот чудосписок со 100 элементами. Список на картинке как раз на VTV.

    Собственно вопрос, улучшилась ли ситуация в XE5? А то тут говорят производительность норм… Насколько сложный был гуй? Было что-то сложнее картинки, трех кнопок и двух чекбоксов? Просто на FMX который был в Delphi XE3 написать что-то по сложности сопоставимое с Delphi IDE — невозможно на том FMX который с ним поставлялся. Простенькое приложение написать можно, но зачем оно на мобильных платформах? Батарею жрать? А на десктопах под винду — VCL шустрее.

    p.s. У меня есть наработки типа библиотеки контролов, которые используют OpenGL для вывода графики. Когда то, когда навелосипедил для себя (когда еще никаких этих FireMonkey не было). Плюнул развивать это дело, когда выкатили FMX c XE. Но даже сейчас мои контролы работают шустрее. Потому что я заморачивался по поводу оптимизаций. Эх, знал бы что этот цирк с FMX затянется так…
    • 0
      Гуй был простой, чтобы любая девочка разобралась. Главный напряг ресурсов процессора приходится у меня на моменты, когда анимация контрола происходит одновременно с проигрыванием звукового файла. На Виндах явно заметно дёрганье анимации, т.е. что-то перегружено. Как ни странно, на Андроиде такого нет. Вот это поразительно. К слову, одни и те же 3D сцены, сделанные на Юнити, имея на десктопе фпс порядка 150-200, на этом же планшете падают в фпс до 15-20, т.е. на порядок.
  • 0
    try
      Create;
    finally
      Free;
    end
    


    аж глаз режет, никогда не понимал такого подхода — всегда пишу так:

    Create;
    try
      ..  
    finally
      Free;
    end
    
    • +1
      А если нужно создать два объекта то писать вот так?
      obj1 := TMyObj1.Create;
      try
        obj2 := TMyObj2.Create;
        try
          ....
        finally
          obj2.Free;
        end;    
      finally
        obj1.Free;
      end;
      

      Я лично предпочитаю так:
      obj1 := nil;
      obj2 := nil;
      try
        obj1 := TMyObj1.Create;
        obj2 := TMyObj2.Create;
        ...
      finally
        obj1.Free;
        obj2.Free;
      end;
      
      • 0
        Если в конструкторе вылетает исключение, то у Вас по любому будет отрабатываться деструктор, а это черевато.
        • +1
          Чревато не знать делфи. Free если что делает проверку на nil. Код который я привел абсолютно корректен.
          • –3
            А вдруг я перекрыл Free? ) Не говорите ерунды, finally нужен для освобождения памяти, если память не была выделена, то и освобождать ничего не надо. Перепишите свой пример с GetMem/FreeMem, например, и все станет ясно.
            • +5
              Это вы говорите ерунду. Метод TObject.Free — не виртуальный, и если вы его перекрыли — то ССЗБ.
              Не знаю что вам не ясно в примере выше, но вот то же самое на GetMem-ах
              item1 := nil;
              item2 := nil;
              try
                GetMem(item1, SizeOf(item1^));
                GetMem(item2, SizeOf(item2^));
                ...
              finally
                if assigned(item1) then FreeMem(item1);
                if assigned(item2) then FreeMem(item2);
              end;
              

              p.s. Видимо не стоит ввязываться в спор о Delphi с вашими знаниями этого языка.
  • –2
    Как не знали дельфисты про MVC/MVVP, так и продолжают лепить копрокод в конце 2013-го.

    • НЛО прилетело и опубликовало эту надпись здесь
      • –6
        Вы абсолютно правы. Все дельфисты — профессиональные говнокодеры, неспособные к написанию сложных приложений. MVC им ни о чем не говорит, а всякие ActionManager'ы и LiveBinding запилили в Дельфу просто так, чтобы показать «что и мы так можем».
        А Эмбаркадеро финансируется мировой закулисой. Потому что не может быть такого, что нашлось достаточно разработчиков, готовых потратиться на никому ненужную XE3-4-5.
        • 0
          iandarken, о себе: «Раздолбай-сисадмин, геймер-задрот и зануда».

          Простите, из вашего профиля не совсем ясно какой язык вы предпочитаете? У вас вообще есть собственные разработки, раз вы делаете такие глобальные выводы?
    • +1
      > Как не знали дельфисты про MVC
      Тащемта, делфя сама по себе — уже MVC.
      То, что вы имеете в виду — это MVC поверх MVC.
      Спорный вопрос, в общем.
  • +1
    Люблю Delphi с детства, был момент когда думал что делфи каюк настал, но вижу, что команда не сдается и так просто не уступит.
    Я надеюсь, что делфи будет жить и баги устранят. Спорить чем делфи лучше или хуже не собираюсь, у меня достаточно опыта было на других языках они тоже не совершенны.
  • +2
    Спасибо, очень интересный опыт.

    Как раз занимаюсь Android-разработкой, а на Дельфи пришлось плотно поработать в прошлом месяце (поддерживал немного Windows-СУБД на Delphi XE2). До 2009 года писал на Delphi 7 более двух лет.
    В общем, с одной стороны хорошо, что появляются такие возможности выбора, но с другой строны лично я добровольно с Java на Delphi никогда бы не перешёл вернулся.

    Простые причины на поверхности:
    * Стандартными средствами можно легко разрабатывать под Android, не вкладывая денег в ПО. Сейчас работаю в Ubuntu и с Android Studio. В случае Delphi — это покупка Windows + самой среды разработки как минимум (?)
    * Уровень документации. Официальная документация просто отличная + куча тематических блогов, StackOverflow, хабр в конце-концов. Нерешаемых проблем практически нет.
    * Просто эстетическое удовлетворение от работы и удобство IntelliJ IDEA Android Studio. После неё XE2 — это просто адъ и израиль какой-то :) Надеюсь в XE5 всё гораздо лучше, никогда её не видел.

    Конечно, это всё касается чистого Андроида, задач писать под iOS/Windows Phone/Whatever пока не возникало.
  • 0
    Насколько помню Delphi, в этом коде есть две потенциальные ошибки:

    try
    StrList := TStringList.Create;
    //some code here
    finally
    DeleteFile(filePrefix + tempFile);
    StrList.Free;
    end;

    Во-первых, если исключение стреляет в конструкторе, автоматически выполняется деструктор и объект не создаётся. Таким образом, TStringList.Create нужно выносить за пределы try-finally блока.
    Во-вторых, если в DeleteFile тоже стрельнёт исключение, StrList не освободится, поэтому в finally лучше размещать по одному действию.
    Таким образом, исправленный код будет выглядеть так:

    StrList := TStringList.Create;
    try
    try
    //some code here
    finally
    DeleteFile(filePrefix + tempFile);
    end;
    finally
    StrList.Free;
    end;

    • 0
      Вы почти правы. В первом случае проблема не столько в том что TStringList.Create внутри try, а в том что в StrList может быть не nil до входа в try, соответственно код лучше переделать либо как вы сказали на:
      StrList := TStringList.Create;
      try
        //some code here
      finally
        StrList.Free;
      end;
      

      либо на:
      StrList := nil;
      try
        StrList := TStringList.Create;
        //some code here
      finally
        StrList.Free;
      end;
      

      Я лично предпочитаю второй способ, потому что если надо создать несколько объектов — можно все в один try впихнуть.

      Во втором же случае — в DeleteFile исключение не должно стрельнуть, т.к. функция вызывает системную, возвращающую код ошибки.

      Таким образом код содержит потенциально одну проблему, с TStringList.Create, который может стрельнуть только одним исключением: EOutOfMemory, при этом будет утечка в один TStringList
      • 0
        Верно, я говорил именно о неинициализированной переменной. )

        По поводу обработки двух и более объектов в try-finally в этом конкретном случае вы совершенно правы.

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

        Поэтому я и назвал это «потенциальной ошибкой» :)
        • 0
          Стрелять исключениями в деструкторе в делфи — это сразу же стрелять себе в ногу, ибо не отработает TObject.FreeInstance, а соответственно и TObject.CleanupInstance. Грубо говоря имеем сразу же утечку памяти еще до того, как код выйдет за пределы finally.
          Кроме того делфя сама создает один блок финализации для автоматически финализируемых типов, и изменить мы это не можем. Поэтому бросать исключения в деструкторе — нельзя.
          • 0
            Безусловно :)
            Вот только свобождение ресурсов — это не только деструктор и освобождение памяти, согласны?
            И не всегда освобождение этого ресурса пишем мы, есть и сторонние библиотеки.

            • 0
              А, ну да, видимо я вас не так понял, когда вы говорили про общий случай. Я думал вы имели ввиду освобождение объектов в общем случае.

              Тогда позвольте мне немного расширить ваше условие:
              Но в общем случае рекомендуют использовать один try-finally блок на один ресурс для ресурсов, которые могут создавать исключения на этапе освобождения.
  • 0
    По поводу try..finally. Это был псевдокод, показывающий, что на обеих платформах можно спокойно использовать Free для освобождения объекта.

    Если по сути дискуссии — использование того или иного подхода зависит от того, велика ли вероятность ошибки в конструкторе. Ошибка, например, при создании стринглиста, крайне маловероятна (кончилась память? Ничего другого сразу и не придумаешь.).

    Предполагать, что ошибка может возникнуть в любом операторе программы, конечно, можно, но отражать это в коде имеет смысл только для самых наиболее вероятных мест.
  • –1
    Простите за не очень позитив, но по-моему, это костыли, на других концах которых приделаны грабли.

    Ещё раз прошу прощения.

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