уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Не прекращаю попыток в свободное от основной работы время разрабатывать небольшое приложение в Delphi для Android. Последнее, с чем пришлось столкнуться — работа с диалогами (InputQuery, InputBox, ShowMessage и тому подобное) при разработке для Android. Может я очень уж сильно отстал от последних нововведений в Delphi, а может эти нововведения и не нововведения вовсе (хотя документация Embarcadero свидетельствует об обратном), однако, в Delphi 10.1 Berlin большинство методов работы с диалогами были помечены как deprecated. И для работы с диалогами в FMX нам предлагается использовать вспомогательный класс TDialogService. Решил немного разобраться с тем, что это за зверь и какие сюрпризы в этом случае нам заготовлены при разработке приложений андроид в delphi.

Для начала, немного официальной документации. Что было помечено директивой deprecated и что предлагается использовать взамен:

Deprecated Members New Members
  • FMX.Dialogs.ShowMessage
  • FMX.Dialogs.ShowMessageFmt
  • FMX.Dialogs.ShowMessagePos
  • ShowMessageAsync
  • ShowMessageSync
  • FMX.Dialogs.MessageDlg
  • FMX.Dialogs.MessageDlgPos
  • FMX.Dialogs.MessageDlgPosHelp
  • FMX.Platform.IFMXDialogService.MessageDialog
  • MessageDialogAsync
  • MessageDialogSync
  • FMX.Dialogs.InputBox
  • FMX.Dialogs.InputQuery
  • FMX.Platform.IFMXDialogService.InputQuery
  • InputQueryAsync
  • InputQuerySync

При этом методы ShowMessage и ShowMessageFmt, несмотря на их наличие в разделе deprecated members, не являются таковыми, однако нам рекомендуется использовать вместо них аналогичный синхронный или асинхронный вариант. Хорошо, посмотрим, как использовать нововведение.

Модуль FMX.DialogService

В этом модуле содержится всего один вспомогательный класс с несколькими классовыми методами, назначение которых, думаю, понятно по их названию:

  TDialogService = class
  public type
    TPreferredMode = (Platform, Async, Sync);
 
  strict private
    class var FPreferredMode: TPreferredMode;
    class var FInSyncMode: Boolean;
    class procedure SetPreferredMode(const PreferredMode: TPreferredMode); static;
 
  public
    class constructor ClassCreate;
 
    class procedure ShowMessage(const AMessage: string); overload; class procedure ShowMessage(const AMessage: string; const ACloseDialogProc: TInputCloseDialogProc); overload; 
    class procedure ShowMessage(const AMessage: string; const ACloseDialogEvent: TInputCloseDialogEvent; const AContext: TObject = nil); overload; 
 
    class procedure MessageDialog(const AMessage: string; const ADialogType: TMsgDlgType; const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn; const AHelpCtx: LongInt; const ACloseDialogProc: TInputCloseDialogProc); overload; 
    class procedure MessageDialog(const AMessage: string; const ADialogType: TMsgDlgType; const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn; const AHelpCtx: LongInt; const ACloseDialogEvent: TInputCloseDialogEvent; const AContext: TObject = nil); overload; 
    class procedure InputQuery(const ACaption: string; const APrompts: array of string; const AValues: array of string; const ACloseQueryProc: TInputCloseQueryProc); overload;
 
    class procedure InputQuery(const ACaption: string; const APrompts: array of string; const AValues: array of string; const ACloseQueryEvent: TInputCloseQueryWithResultEvent; const AContext: TObject = nil); overload; 
 
   class property PreferredMode: TPreferredMode read FPreferredMode write SetPreferredMode; 
end;

Использовать класс довольно просто. Например, мы хотим показать InputQuery. Вызываем соответствующий метод класса TDialogService:

TDialogservice.InputQuery('Введите что-нибудь', ['Ввод чего-нибудь'], [''],
    procedure(const AResult: TModalResult; const AValues: array of string)
      begin
        case AResult of
          mrOk:
             result:=AValues[0];
          mrCancel:
             result:='Ввод чего-нибудь отменен';
        end;
      end
    );

Свойство PreferredMode позволяет переключаться между синхронным и асинхронным режимами показа диалогов:

public type
  TPreferredMode = (Platform, Async, Sync);

По умолчанию свойство имеет значение Platform, то есть режим работы определяется операционной системой, однако нам не запрещается это свойство изменить при разработке под Android на Sync и тогда…

Синхронный или асинхронный InputQuery?

И когда я это сделал, то есть сменил значение свойства с Platform на Sync, тогда же и вспомнил старую, как мир заповедь: прежде, чем начинать использовать что-то — читай документацию. А в документации ясно и понятно сказано, что TDialogService использует в работе или IFMXDialogServiceSync или  IFMXDialogServiceAsync (в зависимости от того, что мы попросим в свойстве PreferredMode). Поддержка этих интерфейсов в разных операционных системах следующая:

IFMXDialogServiceSync IFMXDialogServiceAsync
Windows yes yes
OS X yes yes
iOS yes yes
Android remove yes

Как бы вы не старались и что бы вы не предпринимали в Android диалоги будут работать Асинхронно.

Что это значит для нас? Ну, например, при разработке под Android уже не получится написать, что-то наподобие вот такого:

if InputQuery('Введите пароль','Пароль',Value) then
  Password:=Value;
//Тут что-то делаем с Password

Во-первых, потому, что теперь надо писать так:

TDialogservice.InputQuery('Введите пароль', ['Пароль'], [''],
    procedure(const AResult: TModalResult; const AValues: array of string)
      begin
        case AResult of
          mrOk:
             Password:=AValues[0];
          mrCancel:
             Password:='Ввод пароля отменен';
        end;
      end
    );
//Тут что-то делаем с Password

А во-вторых, так как вызов асинхронный, то программа не будет ждать пока пользователь нажмет на «Ok» или «Cancel», а сразу пойдет работать дальше. То есть сразу после показа диалога уйдет на строку

//Тут что-то делаем с Password

И это придётся каким-либо образом учитывать, если вы хотите разрабатывать приложения для андроид в delphi и использовать в этих приложениях InputQuery, InputBox и другие диалоги.

Кстати, про InputBox

Как вы могли заметить выше, в TDialogService нет реализации метода InputBox. Также его нет и в интерфейсах IFMXDialogServiceSync и IFMXDialogServiceAsync. Так что про использование этого диалога в FMX можно забыть и не вспоминать, а использовать вместо него InputQuery.

В общем-то, ничего особенно критичного не произошло, в связи с переходом на TDialogService для показа диалогов в Delphi 10.1, но, признаюсь, после долгого перерыва работы в этой области, пришлось немного пошерстить документацию в поисках ответа на вопрос «Почему в андроид InputBox работает не так, как я попросил (синхронно)?». А ответ-то, как оказалось, лежал на самом видном месте — в документации Emabrcedero. Всем удачных разработок в Delphi 10.1 для Android и до новых встреч на страницах блога webdelphi.ru ;)

Книжная полка

Описание Подробно рассматривается библиотека FM, позволяющая создавать полнофункциональное программное обеспечение для операционных систем Windows и OS X, а также для смартфонов и планшетных компьютеров, работающих под управлением Android и iOS
купить книгу delphi на ЛитРес
Описание: Книга рассчитана на подготовленного пользователя ПК, желающего самостоятельно научиться программировать и разрабатывать приложения и базы данных в среде Delphi. Опытные программисты смогут использовать издание как справочник. В тексте подробно описаны более 80 компонентов VCL, функции Object Pascal и Win32 API.
купить книгу delphi на ЛитРес

 

0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии