Partilhar via


Criar aplicações de tela grandes e complexas

A maioria dos artigos nesta seção da documentação aborda o desempenho em tempo de execução dos aplicativos conforme experimentado pelas pessoas que os usam. Este artigo aborda o desempenho do aplicativo conforme experimentado pelas pessoas que os criam.

À medida que os aplicativos se tornam maiores e mais complexos, o Power Apps Studio precisa carregar e gerenciar um número maior de controles, fórmulas e fontes de dados, tudo com interdependências que crescem exponencialmente. O Power Apps Studio pode levar mais tempo para carregar, e recursos como o IntelliSense e a codificação de cores podem atrasar. Use as recomendações a seguir para trabalhar melhor com aplicativos grandes e complexos no Power Apps Studio. Eles também podem ajudar a melhorar o desempenho de tempo de execução de seus aplicativos.

Os exemplos neste artigo usam a solução de exemplo de Resposta de Emergência Hospitalar.

Use App.Formulas em vez de App.OnStart

Gorjeta

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 maneira de reduzir o tempo de carregamento do Power Apps Studio e do seu aplicativo é substituir a inicialização de variáveis e coleções em App.OnStart por fórmulas nomeadas em App.Formulas.

Vejamos o exemplo a seguir, 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, seu aplicativo deve avaliar essas chamadas set and Collect em ordem antes de exibir a primeira tela, o que faz com que o aplicativo carregue mais lentamente. E como todo o App.OnStart deve ser considerado como um todo, a ordem preservada e os erros agregados antes de retornar o resultado final, a fórmula é complexa para o Power Apps Studio analisar.

Há uma maneira melhor. Use App.Formulas em vez disso e defina essas variáveis e coleções como fórmulas nomeadas, como no exemplo a seguir.

// 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 mudança pode parecer pequena, mas pode ter um enorme impacto. Como cada fórmula nomeada é independente das outras, o Power Apps Studio pode analisá-las de forma independente, dividindo efetivamente um App.OnStart grande em partes menores. Vimos o tempo de carregamento do Power Apps Studio cair em até 80% apenas com essa alteração.

Seu aplicativo também carrega mais rápido porque não precisa avaliar essas fórmulas até precisar do resultado. A primeira tela do aplicativo é exibida imediatamente.

As fórmulas nomeadas não podem ser usadas em todas as situações porque você não pode modificá-las ou usá-las com set. Algumas situações requerem o uso de uma variável de estado que pode ser modificada. Set é perfeito para essas situações e tu deves continuar a utilizá-lo. Mas, na maioria das vezes, você está usando variáveis globais no OnStart para configurar valores estáticos que não mudam. Nesses casos, uma fórmula nomeada é a melhor escolha.

Como as fórmulas nomeadas são imutáveis, o prefixo var (abreviação de "variável") como uma convenção de nomenclatura não é mais apropriado. Não alteramos os nomes neste exemplo porque isso exigiria alterações no resto do aplicativo para corresponder.

É tentador colocar uma fórmula nomeada no App.OnStart, mas não o faça. Eles não pertencem lá. Como uma propriedade de comportamento On, App.OnStart avalia cada uma das suas instruções por ordem, criando variáveis globais e interagindo com bases de dados apenas uma vez, quando a aplicação é carregada. Fórmulas nomeadas são fórmulas que definem como calcular algo sempre que necessário e são sempre verdadeiras. É essa natureza da fórmula que lhes permite ser independentes e permite que a aplicação termine de carregar antes de serem avaliadas.

Divida 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.

Nossos estudos mostraram que quase todos os aplicativos com um longo tempo de carregamento para o Power Apps Studio têm pelo menos uma fórmula de mais de 256.000 caracteres. Algumas aplicações com os tempos de carregamento mais longos têm fórmulas de mais de 1 milhão de caracteres. Fórmulas que durante muito tempo exerceram uma pressão significativa no Power Apps Studio.

Para piorar as coisas, ao copiar e colar um controle com uma fórmula longa, a fórmula é duplicada nas propriedades do controlo sem que o usuário perceba. O Power Apps é modelado de acordo com o Excel, onde várias cópias de uma fórmula são comuns. No entanto, no Excel, as fórmulas são limitadas a uma expressão e são limitadas a 8.000 caracteres. As fórmulas do Power Apps podem crescer muito mais com a introdução da lógica imperativa e do operador de encadeamento (; ou ;;, dependendo da localidade).

A solução geral é dividir fórmulas longas em partes menores e reutilizar as partes, como fizemos na seção anterior quando alteramos as instruções set/Collect em App.OnStart para fórmulas nomeadas em App.Formulas. Em outras linguagens de programação, as partes reutilizáveis são frequentemente referidas como sub-rotinas ou funções definidas pelo usuário. Você pode pensar em fórmulas nomeadas como uma forma simples de função definida pelo usuário sem parâmetros ou efeitos colaterais.

Use fórmulas nomeadas em todos os lugares

No exemplo anterior, usamos fórmulas nomeadas como um substituto para App.OnStart. No entanto, você pode usá-los para substituir um cálculo em qualquer lugar em um aplicativo.

Por exemplo, um dos ecrãs na solução de exemplo de Resposta de Emergência Hospitalar inclui essa lógica em 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 em um conjunto de fórmulas nomeadas. Também torna a fórmula mais fácil de ler.

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ão avaliadas somente quando seus valores são necessários. Se a intenção original de usar Screen.OnVisible era adiar o trabalho até que o ecrã fosse mostrado, então o trabalho continua a ser adiado na forma de fórmulas nomeadas globais em App.Formulas.

Use a função Com

Você também pode usar a função With em uma fórmula para dividir a lógica. Crie um registro no primeiro parâmetro com os valores que você deseja usar como campos e, em seguida, use esses campos no segundo parâmetro para calcular o valor de retorno de With. 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
           }
    )

Uma desvantagem de usar Com esta maneira é que MyFacility não pode usar MyRegion porque eles são definidos na mesma função Com , um problema que não está presente com 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 canvas são usados com mais frequência para criar um controle de interface do usuário que pode ser colocado no canvas como um controle. Você também pode usá-los sem colocá-los na interface do usuário para executar cálculos com propriedades de saída personalizadas como uma alternativa às 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, eles são mais difíceis de configurar e usar do que fórmulas nomeadas.

Para dividir a lógica:

  1. No Power Apps Studio, alterne para a guia Componentes no modo de exibição Árvore.
  2. Crie um novo componente.
  3. No painel Propriedades , ative o escopo do aplicativo Access.
  4. Adicione uma propriedade personalizada.
  5. Defina o Tipo de propriedade como Saída e o Tipo de dados conforme apropriado.
  6. Selecione Criar.
  7. No seletor de propriedades ao lado da barra de fórmulas na parte superior da tela, selecione a nova propriedade.
  8. Escreva a fórmula para a lógica dividir e reutilizar.

Para usar a lógica:

  1. Mude para o separador Ecrãs na Árvore de Visão.
  2. No painel Inserir, expanda Personalizado e insira o componente.
  3. Para calcular um valor com a propriedade, use ComponentName.PropertyName.

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

A lógica imperativa é usada para modificar o estado com set and Collect, notificar o usuário com Notify, navegar para outra tela ou aplicativo com Navigate and Launch e gravar valores em um banco de dados com Patch, SubmitForm ou RemoveIf.

As fórmulas nomeadas e as propriedades de saída personalizadas do componente canvas não suportam lógica imperativa. Uma maneira comum de dividir a lógica imperativa é usar a propriedade OnSelect de um controle oculto.

  1. Adicione um controle Button a uma tela.
  2. Defina a propriedade OnSelect para a lógica imperativa que você deseja executar.
  3. Defina a propriedade Visible como false, pois não há necessidade de o usuário ver ou interagir com ela.
  4. Chame Select( Button ) quando pretende executar a lógica imperativa.

Por exemplo, uma das telas em nosso exemplo tem a seguinte propriedade OnSelect em um controle Button . (Este exemplo simples é apenas para fins ilustrativos. Normalmente, você só usaria essa técnica 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 pouco mais complicadas funcionam em telas, como usar o controle Toggle , definir OnCheck para a lógica que você deseja executar e definir Default para uma variável global e, em seguida, alternar a variável global com Set( global, true ); Set( global, false ) no ponto em que você deseja executar a lógica.

Neste exemplo, alguma divisão lógica já havia sido feita. O comentário menciona que "Ações subsequentes podem ser encontradas no OnSuccess". Esse evento executa a lógica imperativa depois que o registro foi enviado com êxito, uma solução específica para a função SubmitForm .

Particionar o aplicativo

Alguns aplicativos crescem para milhares de controles e centenas de fontes de dados, o que torna o Power Apps Studio mais lento. Tal como acontece com fórmulas longas, as aplicações grandes podem ser divididas em secções mais pequenas que trabalham 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 amostral de Resposta de Emergência Hospitalar. Aplicativos separados gerenciam cada uma das principais áreas do aplicativo geral. Os aplicativos compartilham um componente comum do painel de controle por meio de uma biblioteca de componentes que cada aplicativo mostra em sua tela de inicialização:

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 usuário seleciona uma área, o componente usa metadados sobre os aplicativos disponíveis e qual aplicativo está hospedando o componente. Se a tela desejada estiver neste aplicativo (ou seja, ThisItem.Screen não estiver em branco), uma chamada Navigate será feita. Mas se a tela desejada estiver em um aplicativo diferente (ou seja, ThisItem.PowerAppID não estiver em branco), uma função Launch será usada com a ID do aplicativo de 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 no aplicativo original é perdido quando outro aplicativo é iniciado. Certifique-se de salvar qualquer estado antes de chamar a função Iniciar . Grave-o em um banco de dados, chame SaveData ou passe o estado para o aplicativo de destino com parâmetros que são lidos com a função Param .

Aplicativo controlado por modelo com páginas personalizadas

As seções também podem ser implementadas como páginas personalizadas. As páginas personalizadas funcionam como uma mini aplicação canvas com um contêiner de aplicação orientada por modelos para navegação.