Создавайте большие и сложные приложения на основе холста

Большинство статей в этом разделе документации посвящены производительности приложений во время выполнения с точки зрения конечных пользователей. В этой статье рассматривается производительность приложений с точки зрения их создателей.

Поскольку приложения становятся большими и сложными, Power Apps Studio требуется загружать большое количество элементов управления, формул и источников данных и управлять ими, а их взаимозависимости растут в геометрической прогрессии. Время загрузки Power Apps Studio может замедляться, а такие функции, как IntelliSense и цветовое кодирование, могут работать с задержкой. Используйте рекомендации, чтобы лучше работать с большими и сложными приложениями в Power Apps Studio. Они также могут помочь повысить производительность ваших приложений во время выполнения.

Примеры в этой статье основаны на примере решения Hospital Emergency Response.

Используйте App.Formulas вместо App.OnStart

Совет

Вы можете использовать функцию With и настраиваемые выходные свойства компонента холста в качестве альтернативы именованным формулам.

Лучший способ сократить время загрузки для Power Apps Studio и вашего приложения конечного пользователя — заменить инициализацию переменных и коллекций в App.OnStart именованными формулами в App.Formulas.

Давайте посмотрим на следующий пример, в котором используется App.OnStart.

// Get the color of text on a dark background.
Set(varColorOnDark,RGBA(0, 0, 0, 1));

// Get the color of the menu icons.
Set(varColorMenuIcon,"#0070a9");

// Get the styles for a form.
Set(varFormStyle,
    {
        DataCard: { Height: 50 },
        Title: { Height: 50, Size: 21, Color: varColorOnDark },
        Control: { Height: 50, Size: 18 },
        Label: { Size: 18, Color: varColorOnDark }
    }
);

ClearCollect(
    FacilitiesList,
    ForAll(
        Facilities,
        { Name: 'Facility Name', Id: Facility }
    )
);
If(
    Not IsBlank(Param("FacilityID")),
    Set(ParamFacility,
        LookUp(
            FacilitiesList,
            Id = GUID(Param("FacilityID"))
        ).Name
    );
);

Как последовательность операторов, эти вызовы Set и Collect должны оцениваться вашим приложением по порядку до отображения первого экрана, что замедляет загрузку приложения. Поскольку весь элемент App.OnStart должен рассматриваться как единое целое, порядок сохраняется и ошибки суммируются до возвращения окончательного результата. Эта формула сложна для анализа в Power Apps Studio.

Есть более удобный способ. Используйте App.Formulas вместо этого и определите эти переменные и коллекции в качестве именованных формул, как в следующем примере.

// Get the color of text on a dark background.
varColorOnDark = RGBA(0, 0, 0, 1);

// Get the color of the menu icons.
varColorMenuIcon = "#0070a9";

// Get the styles for a form.
varFormStyle = 
    {
        DataCard: { Height: 50 },
        Title: { Height: 50, Size: 21, Color: varColorOnDark },
        Control: { Height: 50, Size: 18 },
        Label: { Size: 18, Color: varColorOnDark }
    };

FacilitiesList =
    ForAll(
        Facilities,
        { Name: 'Facility Name', Id: Facility }
    );

ParamFacility = 
    If( Not IsBlank(Param("FacilityID")),
        LookUp(
            FacilitiesList,
            Id = GUID(Param("FacilityID"))
        ).Name,
        Blank()
    );

Это изменение может показаться незначительным, но оно может иметь огромное влияние. Поскольку каждая именованная формула независима от других, Power Apps Studio может анализировать их независимо, эффективно разделяя большой App.OnStart на более мелкие части. После внесения только этого изменения время загрузки Power Apps Studio сокращалось на 80 %.

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

Именованные формулы нельзя использовать во всех ситуациях, потому что их нельзя изменить или использовать с параметром Set. В некоторых ситуациях требуется использование переменной состояния, которую можно изменить. Параметр Set идеально подходит для таких ситуаций, и вы должны продолжать его использовать. Но чаще всего вы будете использовать глобальные переменные в OnStart для установки статических значений, которые не изменяются. В таких случаях именованная формула является лучшим выбором.

Поскольку именованные формулы неизменяемы, префикс var (сокращение от «переменная») в качестве соглашения об именовании больше не подходит. Мы не изменили имена в этом примере, потому что для этого потребовались бы изменения в остальной части приложения.

Заманчиво поместить именованную формулу в App.OnStart. Но ей там просто не место. В качестве свойства поведения On (при, во время), App.OnStart оценивает каждый из своих операторов по порядку, создавая глобальные переменные и обращение к базам данных только один раз при загрузке приложения. Именованные формулы — это формулы, которые определяют, как что-то вычислять, когда это необходимо, и всегда верны. Именно эта природа формулы позволяет им быть независимыми и позволяет приложению завершить загрузку до того, как они будут оценены.

Разбиение длинных формул

App.OnStart является одним из самых серьезных нарушителей для длинных формул и, безусловно, именно с него следует начинать, но это не единственный случай.

Наши исследования показали, что почти во всех приложениях с длительным временем загрузки Power Apps Studio есть хотя бы одна формула, длина которой превышает 256 000 символов. В некоторых приложениях с самым долгим временем загрузки формулы содержат более 1 миллиона символов. Формулы, которые значительно увеличивает нагрузку на Power Apps Studio.

Что еще хуже, копирование и вставка элемента управления с длинной формулой приведет к дублированию формулы в свойствах элемента управления без ее реализации. Power Apps создан по образцу Excel, где часто используется несколько копий формулы. Однако формулы Excel ограничены одним выражением и не могут превышать 8000 символов. Формулы Power Apps могут стать намного длиннее с введением императивной логики и оператора цепочки (; или ;; в зависимости от языкового стандарта).

Обычный решением является разбиение длинных формул на более мелкие части и использование этих частей, как было сделано в предыдущем разделе путем преобразования инструкций Set/Collect в App.OnStart в именованные формулы в App.Formulas. В других языках программирования эти повторно используемые части часто называются подпрограммами или определяемыми пользователем функциями. Именованные формулы можно рассматривать как простую форму определяемых пользователем функций без параметров и без побочных эффектов.

Используйте именованные формулы везде

В предыдущем примере мы использовали именованные формулы вместо App.OnStart. Однако вы можете использовать их для замены вычислений в любом месте приложения.

Например, один из экранов в примере решения Hospital Emergency Response включает следующую логику в Screen.OnVisible:

ClearCollect(
    MySplashSelectionsCollection,
    {
        MySystemCol: First(
            Filter(
                Regions,
                Region = MyParamRegion
            )
        ).System.'System Name',
        MyRegionCol: First(
            Filter(
                Regions,
                Region = MyParamRegion
            )
        ).'Region Name',
        MyFacilityCol: ParamFacility,
          MyFacilityColID:  LookUp(
            FacilitiesList,
            Id = GUID(Param("FacilityID"))
        ).Id
    }
); 

Эту формулу можно разбить на набор именованных формул. Это также облегчает чтение формулы.

MyRegion = LookUp(
                    Regions,
                    Region = MyParamRegion
           );

MyFacility = LookUp(
                    FacilitiesList,
                    Id = GUID(Param("FacilityID")
            );

MySplashSelectionsCollection = 
    {
        MySystemCol: MyRegion.System.'System Name',
        MyRegionCol: MyRegion.'Region Name',
        MyFacilityCol: ParamFacility,
        MyFacilityColID:  MyFacility.Id
    };

ParamFacility была извлечена как именованная формула ранее, когда мы переместили большинство вызовов Set из App.OnStart в именованные формулы в App.Formulas.

Именованные формулы оцениваются только тогда, когда их значения необходимы. Если исходной целью использования Screen.OnVisible была задержка работы, пока не будет показан экран, то эта работа по-прежнему будет отложена как именованные формулы в App.Formulas.

Использование функции With

Вы также можете использовать функцию With в формуле для разделения логики. Создайте запись в первом параметре с нужными значениями в качестве полей, а затем используйте эти поля во втором параметре для вычисления возвращаемого значения из With. Например, приведенный выше пример можно записать в виде всего одной именованной формулы:

MySplashSelectionsCollection = 
    With( { MyRegion: LookUp(
                            Regions,
                            Region = MyParamRegion
                      ),
            MyFacility: LookUp(
                            FacilitiesList,
                            Id = GUID(Param("FacilityID")
                      ) 
           },
           {
                MySystemCol: MyRegion.System.'System Name',
                MyRegionCol: MyRegion.'Region Name',
                MyFacilityCol: ParamFacility,
                MyFacilityColID:  MyFacility.Id
           }
    )

Одним из недостатков использования With таким образом является то, что MyFacility не может использовать MyRegion, поскольку они определены в пределах одной функции With, — эта проблема отсутствует с именованными формулами. Одним из решений является вложение функций With и использование ключевого слова As, чтобы назвать запись для каждой, чтобы обеспечить легкий доступ ко всем переменным With.

Использование компонентов холста

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

Чтобы разделить логику:

  1. В Power Apps Studio перейдите на вкладку Компоненты в Представлении дерева.
  2. Создание нового компонента.
  3. На панели Свойствавключите Доступ к области приложения.
  4. Добавьте пользовательское свойство.
  5. Задайте для параметра Тип свойства значение Вход и требуемый Тип данных.
  6. Выберите Создать.
  7. Выберите новое созданное свойство в средстве выбора свойств рядом с панелью формул в верхней части экрана.
  8. Напишите формулу для логики с целью разделения и повторного использования.

Чтобы использовать логику:

  1. Перейдите на вкладку Экраны в Представлении дерева.
  2. На панели Вставка разверните пункт Пользовательский и вставьте свой компонент.
  3. Чтобы вычислить значение со свойством, используйте ComponentName.PropertyName.

Используйте Select со скрытым элементом управления для императивной логики

Императивная логика используются для изменения состояния с помощью Set и Collect, уведомления пользователя с помощью Notify, перехода на другой экран или в другое приложение с помощью Navigate и Launch, а также для записи значений обратно в базу данных с помощью Patch, SubmitForm или RemoveIf.

Именованные формулы и выходные свойства компонента холста не поддерживают императивную логику. Распространенным приемом для разделения императивной логики является использование свойства OnSelect скрытого элемента управления.

  1. Добавьте элемент управления Кнопка на экран.
  2. Задайте для свойства OnSelect императивную логику, которую вы хотите выполнить.
  3. Задайте для свойства Visible значение false, поскольку пользователю не нужно видеть его или взаимодействовать с ним.
  4. Вызовите Select( Button ), когда вы хотите выполнить императивную логику.

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

btnAction_17.OnSelect = 
    Trace("Feedback Screen: Submit Button",TraceSeverity.Information);
    If(
        // Proceed if all forms are validated.
        And(
            FormFeedback.Valid
        ),
    
        // Set the updates to static variables.
        Set(updatesFeedback,Patch(Defaults('App Feedbacks'), FormFeedback.Updates));
        // Submit the first form. Subsequent actions can be found in the OnSuccess.
        SubmitForm(FormFeedback);
        ,
    
        Notify("Please complete all fields before proceeding",
               NotificationType.Warning,2000)
    );

Чтобы разделить эту логику на части, мы можем поместить части в отдельные элементы управления Кнопка и выбрать их (Select) из оригинала:

btnTrace.OnSelect = 
    Trace("Feedback Screen: Submit Button",TraceSeverity.Information);

btnSubmit.OnSelect = 
    If(
        // Proceed if all forms are validated.
        And(
            FormFeedback.Valid
        ),
    
        // Set the updates to static variables.
        Set(updatesFeedback,Patch(Defaults('App Feedbacks'), FormFeedback.Updates));
        // Submit the first form. Subsequent actions can be found in OnSuccess.
        SubmitForm(FormFeedback);
        ,
    
        Notify("Please complete all fields before proceeding",
               NotificationType.Warning,2000)
    );

btnAction_17.OnSelect = 
    Select( btnTrace );
    Select( btnSubmit );

Этот метод работает только на одном экране. Другие методы, которые немного сложнее, работают на разных экранах, например, использование элемента управления Переключатель, настройка OnCheck в соответствии с логикой, которую вам нужно выполнить, и настройка Default для глобальной переменной, а затем переключение глобальной переменной с помощью Set( global, true ); Set( global, false ) в точке, где вы хотите выполнить логику.

В этом примере уже было выполнено некоторое разделение логики. В комментарии упоминается, что «Последующие действия можно найти в OnSuccess». Это событие запускает императивную логику после того, как запись была успешно отправлена, решение, специфичное для функции SubmitForm.

Разделение приложения

Некоторые приложения разрастаются до тысяч элементов управления и сотен источников данных, что замедляет работу Power Apps Studio. Как и в случае с длинными формулами, большие приложения можно разделить на более мелкие разделы, которые работают вместе, чтобы создать единый пользовательский интерфейс.

Разделение приложений на основе холста

Один из подходов заключается в реализации разделов в отдельных приложениях на основе холста и использовании функции Launch для перехода между отдельными приложениями и передачи необходимого контекста.

Этот подход использовался в образце решения Hospital Emergency Response. Отдельные приложения управляют каждой из основных областей общего приложения. Приложения используют общий компонент-коммутатор через библиотеку компонентов, которую каждое приложение показывает на экране запуска:

Снимок экрана: приложение на основе холста примера решения Hospital Emergency Response, работающее на телефоне и показывающее компонент коммутатора на холсте.

Когда конечный пользователь выбирает область, компонент использует метаданные о доступных приложениях и о том, в каком приложении размещается компонент. Если нужный экран находится в этом приложении (т. е. ThisItem.Screen не пуст), выполняется вызов Navigate. Но если нужный экран находится в другом приложении (т. е. ThisItem.PowerAppID не является пустым), функция Launch используется с идентификатором целевого приложения и контекстом FacilityID:

If(
    IsBlank(ThisItem.Screen),
    If(IsBlank(ThisItem.PowerAppID), 
        Launch(ThisItem.URL),           
        Launch("/providers/Microsoft.PowerApps/apps/" & ThisItem.PowerAppID, 
               "FacilityID", Home_Facility_DD.Selected.Id)
    ),
    Navigate(
        ThisItem.Screen,
        Fade
    )
);

Состояние в исходном приложении будет потеряно, когда будет запущено другое приложение. Обязательно сохраните любое состояние перед вызовом функции Launch. Запишите его в базу данных, вызовите SaveData или передайте состояние целевому приложению с параметрами, которые считываются с помощью функции Param.

Приложения на основе модели с пользовательскими страницами

Разделы также могут быть реализованы как пользовательские страницы. Пользовательские страницы действуют как мини-приложение на основе холста с контейнером приложения на основе модели для навигации.

Примечание

Каковы ваши предпочтения в отношении языка документации? Пройдите краткий опрос (обратите внимание, что этот опрос представлен на английском языке).

Опрос займет около семи минут. Личные данные не собираются (заявление о конфиденциальности).