Partilhar via


Criar aplicações de tela grandes e complexas

A maior parte dos artigos nesta secção da documentação abrange o desempenho de runtime de aplicações como experienciado pelas pessoas que as utilizam. Este artigo abrange o desempenho de aplicações como experienciado pelas pessoas que as fazem.

À medida que as aplicações se tornam maiores e mais complexas, o Power Apps Studio precisa de carregar e de gerir grandes números de controlos, fórmulas e origens de dados, tudo com interdependências que crescem exponencialmente. O Power Apps Studio pode demorar mais tempo a carregar e as funcionalidades, como o IntelliSense e a codificação de cores pode demorar. Utilize as recomendações que se seguem para trabalhar melhor com aplicações grandes e complexas no Power Apps Studio. Também podem ajudar a melhorar o desempenho de runtime das suas aplicações.

Os exemplos neste artigo usam a Solução de amostra de Resposta a Emergências Hospitalares.

Utilizar App.Formulas em vez de App.OnStart

Dica

Pode usar a função Com de e as propriedades de saída personalizadas do componente de tela como uma alternativa a fórmulas nomeadas.

A melhor forma de reduzir o tempo de carregamento tanto para o Power Apps Studio como para a sua aplicação é substituir a inicialização de variáveis e de coleção em App.OnStart por fórmulas nomeadas em App.Formulas.

Vamos ver o exemplo seguinte, que usa 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
    );
);

Como são uma sequência de instruções, a sua aplicação deve avaliar estas chamadas Definir e Recolher por ordem, antes de poder apresentar o primeiro ecrã, que faz com que a aplicação carregue mais lentamente. E como a App.OnStart deve ser considerada como uma todo, encomenda preservada e erros agregados antes de voltar ao resultado final, a fŕomula é complexa para o Power Apps Studio analisar.

Há uma forma melhor. Utilize App.Formulas, em vez de definir estas variáveis e coleções como fórmulas nomeadas, como no exemplo seguinte.

// 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()
    );

Esta alteração pode parecer pequena, mas pode ter um impacto enorme. Dado que cada fórmula nomeada é independente das outras, p Power Apps Studio pode analisá-las independentemente, dividir eficazmente uma App.OnStart grande em peças mais pequenas. Já vimos que o tempo de carregamento do Power Apps Studio reduz até 80% com esta alteração por si só.

A sia aplicação também carrega mais rapidamente porque não tem de avaliar estas fórmulas até ser necessário o resultado. O primeiro ecrã da aplicação é apresentado imediatamente.

As fórmulas nomeadas não podem ser utilizadas em todas as situações porque não é possível modificá-las nem utilizá-las com Definir. Algumas situações requerem a utilização de uma variável de estado que pode ser modificada. Definir é perfeito para estas situações e deve continuar a utilizá-lo. Contudo, com alguma frequência está a usar variáveis globais em OnStart para configurar valores que não mudam. Nesses casos, uma fórmula nomeada é a melhor escolha.

Uma vez que as fórmulas nomeadas são imutáveis, o prefixo var (abreviatura de "variável") como uma convenção de nomenclatura deixa de ser apropriado. Não alterámos os nomes neste exemplo porque isso iria requerer alterações à restante aplicação para correspondência.

É tentador colocar uma fórmula nomeada em App.OnStart, mas não o faça. Não pertencem aí. Como uma propriedade de comportamento Ativado, a App.OnStart avalia cada uma das instruções por ordem, criando variáveis globais e falando com bases de dados apenas uma vez, quando a aplicação é carregada. As fórmulas nomeadas são fórmulas que definem como calcular algo sempre que necessário e são sempre verdadeiras. É a natureza desta fórmula que lhe permite ser independente e permite que a aplicação conclua o carregamento antes de serem avaliadas.

Dividir fórmulas longas

App.OnStart é um dos piores infratores para fórmulas longas e, definitivamente, é por onde deve começar, mas não é o único caso.

Os nossos estudos mostraram que quase todas as aplicações com um tempo de carregamento demorado para o Power Apps Studio têm, pelo menos, uma fórmula com mais de 256.000 carateres. Algumas aplicações com os tempos de carregamento mais longos têm fórmulas de mais de 1 milhões de carateres. Fórmulas tão longas colocam tensão significativa no Power Apps Studio.

Para piorar, copiar e colar um controlo com uma fórmula longa duplica a fórmula nas propriedades do controlo sem que seja percebido. O Power Apps é modelado depois do Excel, em que são comuns várias cópias de uma fórmula. No entanto, as fórmulas do Excel estão limitadas a uma expressão e têm capacidade para 8.000 carateres. As fórmulas do Power Apps podem crescer muito mais com a introdução de lógica imperativa e do operador de encadeamento (; ou ;;, dependendo da região).

A solução geral é dividir fórmulas longas em partes mais pequenas e reutilizar as partes, como fizemos na secção anterior quando mudámos as instruções Definir/Recolher em App.OnStart para fórmulas nomeadas em App.Formulas. Noutras linguagens de programação, as partes reutilizáveis são, muitas vezes, referidas como subrotinas ou funções definidas pelo utilizador. Pode pensar nas fórmulas nomeadas como uma forma simples de funções definidas pelo utilizador sem parâmetros ou efeitos colaterais.

Utilizar fórmulas nomeadas em todos os locais

No exemplo anterior, utilizamos fórmulas nomeadas como substituição para o App.OnStart. No entanto, pode utilizá-las para substituir um cálculo em qualquer parte de uma aplicação.

Por exemplo, um dos ecrãs da solução de exemplo de Resposta a Emergências Hospitalares inclui esta lógica no 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
    }
); 

esta fórmula pode ser dividida num conjunto de fórmulas nomeadas. Também facilita a leitura da fórmula.

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
    };

Extraímos ParamFacility como uma fórmula nomeada anteriormente, quando movemos as chamadas Definir de App.OnStart para fórmulas nomeadas em App.Formulas.

As fórmulas nomeadas só são avaliadas quando os respetivos valores são necessários. Se a intenção original de utilizar Screen.OnVisible era adiar o trabalho até que o ecrã fosse mostrado, o trabalho vai continuar a ser adiado como fórmulas nomeadas globais em App.Formulas.

Utilizar a função With

Também pode utilizar a função Com numa fórmula para dividir lógica. Criar um registo no primeiro parâmetro com os valores que quer usar como campos e, em seguida, utilizar esses campos no segundo parâmetro para calcular o valor devolvido de Com. Por exemplo, o exemplo anterior pode ser escrito como apenas uma fórmula nomeada:

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
           }
    )

Um inconveniente da utilização de Com desta forma é que MyFacility não pode usar MyRegion porque estão definidas na mesma função Com, um problema que não acontece nas fórmulas nomeadas. Uma solução é aninhar funções Com e utilizar a palavra-chave Como para nomear o registo para cada um dar acesso as todas as variáveis Com.

Utilizar componentes de tela

Os componentes de tela são, com mais frequência, utilizados para criar um controlo de IU que pode ser colocado na tela, tal como um controlo. Também pode usá-las sem as colocar na IU para efetuar cálculos com propriedades de saída personalizadas como uma alternativa a fórmulas nomeadas. Os componentes de tela são fáceis de partilhar entre aplicações com bibliotecas de componentes e, ao contrário das fórmulas nomeadas, são totalmente suportados. No entanto, não é possível configurar e utilizar fórmulas nomeadas.

Para dividir a lógica:

  1. No Power Apps Studio, mude para o separador Componentes na Vista de árvore.
  2. Criar um novo componente.
  3. No painel Propriedades, ative Aceder ao âmbito da aplicação.
  4. Adicione um propriedade personalizada.
  5. Defina o Tipo de propriedade como Saída e o Tipo de dados, como adequado.
  6. Selecione Criar.
  7. No seletor de propriedades, junto da barra de fórmulas na parte superior do ecrã, selecione a nova propriedade.
  8. Escreva a fórmula para a lógica dividir e reutilizar.

Para utilizar a lógica:

  1. Mude o separador Ecrãs na Vista de árvore.
  2. No painel Inserir , expanda Personalizar e insira o componente.
  3. Para calcular um valor com a propriedade, utilize ComponentName.PropertyName.

Utilizar Selecionar com um controlo oculto para uma lógica imperativa

A lógica imperativa é utilizada para modificar o estado com Definir e Recolher, notificar o utilizador com Notificar, navegar para outro ecrã ou aplicação com Navegar e Iniciar e escrever valores para uma base de dados com Patch, SubmitForm ou RemoveIf.

As fórmulas nomeadas e propriedades de saída personalizadas do componente de tela não suportam lógica imperativa. Uma forma comum de dividir lógica imperativa é utilizar a propriedade OnSelect de um controlo oculto.

  1. Adicione um controlo Botão a um ecrã.
  2. Defina a propriedade OnSelect para a lógica imperativa que pretende executar.
  3. Defina a propriedade Visível como falso, uma vez que não é necessário que o utilizador veja ou interaja com a mesma.
  4. Chame Select( Button ) quando pretende executar a lógica imperativa.

Por exemplo, um dos ecrãs na nossa amostra tem a seguinte propriedade OnSelect num controlo Botão. (Este exemplo simples serve apenas para fins de ilustração. Normalmente, esta técnica só é utilizada para fórmulas mais longas.)

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)
    );

Para dividir esta lógica em partes, podemos colocar partes em controlos Botão separados e Selecioná-los a partir do original:

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 );

Esta técnica só funciona no mesmo ecrã. Outras técnicas que são um trabalho ligeiramente mais complicado em vários ecrãs, como a utilização do controlo Comutador, a definição OnCheck para a lógica que pretende executar e Predefinição de uma variável global e, em seguida, comutar a variável global com Set( global, true ); Set( global, false ) no momento em que pretende executar a lógica.

Neste exemplo, já tinha sido feita alguma divisão lógica. O comentário menciona que "É possível encontrar ações subsequentes em OnSuccess". Este evento executa lógica imperativa após a submissão com êxito do registo, uma solução específica da função SubmitForm.

Particione a aplicação

Algumas aplicações crescem até milhares de controlos e centenas de origens de dados, que lentificam o Power Apps Studio Tal como com fórmulas longas, as aplicações grandes podem ser divididas em secções mais pequenas que funcionam em conjunto para criar uma experiência de utilizador.

Separar aplicações de tela

Uma abordagem é implementar secções em aplicações de tela separadas e usar a função Iniciar para navegar entre as aplicações separadas e transmitir o contexto necessário.

Esta abordagem foi utilizada na Solução de amostra Resposta de Emergência Hospitalar. As aplicações separadas gerem cada uma das principais áreas da aplicação global. As aplicações partilham um componente do painel de navegação comum através de uma biblioteca de componentes que cada aplicação mostra no ecrã de arranque:

Captura de ecrã da aplicação de tela da solução de amostra Resposta a Emergências Hospitalares num telemóvel a mostrar o componente de tela do painel de navegação.

Quando o utilizador seleciona uma área, o componente utiliza metadados sobre as aplicações disponíveis e que aplicação está a alojar o componente. Se o ecrã pretendido estiver nesta aplicação (ou seja, ThisItem.Screen não está em branco), então é feita uma chamada Navegar. Mas, se o ecrã pretendido estiver numa aplicação diferente (ou seja, ThisItem.PowerAppID não está em branco), então é utilizada uma função Iniciar com o ID de Aplicação do destino e o contexto 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
    )
);

O estado na aplicação original é perdido quando é iniciada outra aplicação. Certifique-se de que guarda qualquer estado antes de chamar a função Iniciar. Escreva-o numa base de dados, chame SaveData ou passe o estado para a aplicação de destino com parâmetros que são lidos com a função Param .

Aplicação condicionada por modelo com páginas personalizadas

As secções também podem ser implementadas como páginas personalizadas. As páginas personalizadas agem como uma aplicação de tela em miniatura, com um contentor de aplicações condicionadas por modelo para navegação.

Nota

Pode indicar-nos as suas preferências no que se refere ao idioma da documentação? Responda a um breve inquérito. (tenha em atenção que o inquérito está em inglês)

O inquérito irá demorar cerca de sete minutos. Não são recolhidos dados pessoais (declaração de privacidade).