次の方法で共有


大規模で複雑なキャンバス アプリを構築する

ドキュメントのこのセクションのほとんどの記事では、アプリを使用するユーザーが経験するアプリの実行時のパフォーマンスについて説明します。 この記事では、アプリを作成するユーザーが経験したアプリのパフォーマンスについて説明します。

アプリが大きくなり、複雑になるにつれて、Power Apps Studio では、指数関数的に増加する相互依存関係を持つ多数のコントロール、数式、データ ソースを読み込んで管理する必要があります。 Power Apps Studio の読み込みに時間がかかる場合があり、IntelliSense やカラー コーディングなどの機能が遅れる可能性があります。 Power Apps Studio で大規模で複雑なアプリをより適切に操作するには、次の推奨事項を使用します。 また、アプリのランタイム パフォーマンスの向上にも役立ちます。

この記事の例では、 病院の緊急対応サンプル ソリューションを使用します。

App.OnStart の代わりに App.Formulas を使用する

ヒント

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 は各ステートメントを順番に評価し、グローバル変数を作成し、アプリが読み込まれるときに 1 回だけデータベースと通信します。 名前付き数式は、必要に応 じて 何かを計算する方法を定義する数式であり、常に true です。 この数式の性質により、独立し、アプリが評価される前に読み込みを完了できます。

長い数式を分割する

App.OnStart は長い数式の最悪の違反者の1つであり、間違いなくどこから始めるべきかですが、それは唯一のケースではありません。

Microsoft の調査によると、Power Apps Studio の読み込み時間が長いほぼすべてのアプリには、256,000 文字を超える数式が少なくとも 1 つ含まれています。 読み込み時間が最も長い一部のアプリには、100 万文字を超える数式があります。 長い間 Power Apps Studio に大きな負担をかけた数式。

さらに悪いことに、長い数式を使用してコントロールをコピーして貼り付けると、コントロールのプロパティ内の数式が認識されずに複製されます。 Power Apps は Excel の後にモデル化され、数式の複数のコピーが一般的です。 ただし、Excel の数式では 1 つの式に制限され、上限は 8,000 文字です。 Power Apps の数式は、命令型ロジックとチェーン演算子 (ロケールに応じて; または ;;) の導入により、はるかに長くなる可能性があります。

一般的な解決策は、前のセクションで App.OnStart の /Collect ステートメントを App.Formulas の名前付き数式に変更したときと同様に、長い数式をより小さな部分に分割し、パーツを再利用することです。 他のプログラミング言語では、再利用可能な部分はサブルーチンまたはユーザー定義関数と呼ばれることがよくあります。 名前付き数式は、パラメーターや副作用のない単純な形式のユーザー定義関数と考えることができます。

あらゆる場所で名前付き数式を使用する

前の例では、 App.OnStart の代わりに名前付き数式を使用しました。 ただし、それらを使用して、アプリ内の任意の場所で計算を置き換えることができます。

たとえば、病院の緊急対応サンプル ソリューションの画面の 1 つに 、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を名前付き数式として抽出したのは、App.OnStartのほとんどのSet呼び出しをApp.Formulasの名前付き数式に移動したときです。

名前付き数式は、値が必要な場合にのみ評価されます。 Screen.OnVisible を使用する当初の意図が画面が表示されるまで作業を延期した場合でも、その作業は App.Formulas でグローバルな名前付き数式として延期されます。

With 関数を使用する

数式で With 関数を使用して、ロジックを分割することもできます。 フィールドとして使用する値を含むレコードを最初のパラメーターに作成し、2 番目のパラメーターのこれらのフィールドを使用して With からの戻り値を計算します。 たとえば、前の例は、1 つの名前付き数式として記述できます。

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 を使用する欠点の 1 つは、MyFacilityは同じ MyRegion 関数で定義されているため、を使用できないことです。これは、名前付き数式に存在しない問題です。 1 つの解決策は、 With 関数を入れ子にし 、As キーワードを使用してそれぞれのレコードに名前を付けて、すべての With 変数に簡単にアクセスできるようにする方法です。

キャンバス コンポーネントを使用する

キャンバス コンポーネントは、ほとんどの場合、コントロールと同様にキャンバスに配置できる UI コントロールを作成するために使用されます。 名前付き数式の代わりにカスタム出力プロパティを使用して計算を実行するために、UI に配置せずに使用することもできます。 キャンバス コンポーネントは、コンポーネント ライブラリを使用してアプリ間で簡単に共有でき、名前付き数式とは異なり、完全にサポートされています。 ただし、名前付き数式よりも構成と使用が困難です。

ロジックを分割するには:

  1. Power Apps Studio で、ツリー ビューの [コンポーネント] タブに切り替えます。
  2. 新しいコンポーネントを作成します。
  3. [ プロパティ ] ウィンドウで、 Access アプリのスコープを有効にします。
  4. カスタム プロパティを追加します。
  5. 必要に応じて、 プロパティの種類OutputData 型 に設定します。
  6. を選択してを作成します。
  7. 画面上部の数式バーの横にあるプロパティ ピッカーで、新しいプロパティを選択します。
  8. 分割して再利用するロジックの数式を記述します。

ロジックを使用するには:

  1. ツリー ビューの [画面] タブに切り替えます。
  2. [ 挿入 ]ペインで、[ カスタム ]を展開し、コンポーネントを挿入します。
  3. プロパティを使用して値を計算するには、 ComponentName.PropertyName を使用します

命令型ロジックの非表示コントロールで Select を使用する

命令型ロジックは 、SetCollect を使用して状態を変更し、 通知を使用してユーザーに通知し、 NavigateLaunch を使用して別の画面またはアプリに移動し、 PatchSubmitForm、または RemoveIf を使用してデータベースに値を書き込む場合に使用されます。

名前付き数式とキャンバス コンポーネントのカスタム出力プロパティは、命令型ロジックをサポートしていません。 命令型ロジックを分割する一般的な方法は、非表示コントロールの OnSelect プロパティを使用することです。

  1. ボタン コントロールを画面に追加します。
  2. OnSelect プロパティを、実行する命令型ロジックに設定します。
  3. ユーザーが 表示 または操作する必要がないため、Visible プロパティを false に設定します。
  4. 命令型ロジックを実行する場合は、 Select( Button ) を呼び出します。

たとえば、サンプルの画面の 1 つに 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)
    );

このロジックをパーツに分割するには、部分を個別の Button コントロールに配置し、元の コントロール から 選択 します。

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 が遅くなります。 長い数式と同様に、大規模なアプリは、連携して 1 つのユーザー エクスペリエンスを作成する小さなセクションに分割できます。

独立したキャンバス アプリ

1 つの方法は、セクションを個別のキャンバス アプリに実装し、 Launch 関数を使用して個別のアプリ間を移動し、必要なコンテキストを渡すことです。

このアプローチは、 病院の緊急対応サンプル ソリューションで使用されました。 アプリ全体の各主要領域は、個別のアプリによって管理されます。 アプリは、各アプリがスタートアップ画面に表示するコンポーネント ライブラリを介して共通のスイッチボード コンポーネントを共有します。

電話で実行されている病院の緊急対応サンプル ソリューション キャンバス アプリのスクリーンショット。スイッチボード キャンバス コンポーネントが表示されています。

ユーザーが領域を選択すると、コンポーネントは利用可能なアプリと、コンポーネントをホストしているアプリに関するメタデータを使用します。 目的の画面がこのアプリ内にある場合 (つまり、 ThisItem.Screen は空白ではありません)、 Navigate 呼び出しが行われます。 ただし、目的の画面が別のアプリにある場合 (つまり、 ThisItem.PowerAppID は空白ではありません)、 Launch 関数はターゲットのアプリ ID と 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 関数で読み取られたパラメーターを使用してターゲット アプリに状態を渡します。

カスタム ページを使用したモデル駆動型アプリ

セクションはカスタム ページとして実装することもできます。 カスタム ページは、ナビゲーション用のモデル駆動型アプリ コンテナーを備えたミニ キャンバス アプリとして機能します。