建立大型且複雜的畫布應用程式

本文件章節中大多數的文章都會探討應用程式使用者所體驗到的應用程式執行階段效能。 本文說明應用程式製作者所體驗到的應用程式效能。

隨著應用程式變得越來越大且更形複雜,Power Apps Studio 需要載入並管理更大量的控制項、公式和資料來源,全都有呈指數增長的相互依存性。 Power Apps Studio 可能需要長的時間載入,而 IntelliSense 和彩色編碼等功能可能會有延隔。 使用接下來的建議,以便更好地在 Power Apps Studio 中使用大型且複雜的應用程式。 這些建議也有助於改善應用程式的執行階段效能。

本文中的範例使用醫院緊急回應範例解決方案

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

由於其中是一系列陳述式,因此應用程式必須在顯示第一個畫面之前依序評估這些 SetCollect 呼叫,這會讓應用程式載入速度變得更慢。 而且整個 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 依序評估其其每個陳述式、建立全域變數,然後僅在應用程式載入時,一次指示資料庫。 具名公式是定義每當需要時如何進行某種計算且永遠為 true 的公式。 正是這種公式性質使它們能夠獨立,並可讓應用程式在它們進行評估之前完成載入。

分割長公式

App.OnStart 是長公式的其中一個最嚴重違規者,絕對是您應該開始著手之處,但這不是唯一的情況。

我們的研究表明,幾乎所有在 Power Apps Studio 中載入時間較長的應用程式,都至少有一個超過 256,000 個字元的公式。 某些載入時間最長的應用程式會有超過 1 百萬個字元的公式。 那麼長的公式對 Power Apps Studio 造成巨影壓力。

更糟糕的是,複製並貼上包含長公式的控制項會在不知不覺中重複控制項屬性中的公式。 Power Apps 是仿照 Excel 所建立,其中一個公式有多個複本是常見情形。 不過,在 Excel 中,公式僅限於一個運算式,最多只能有 8,000 個字元。 隨著命令式邏輯和鏈結運算子 (;;;,視地區設定而定) 的引進,Power Apps 公式可能會變得更長。

一般解決方案是將長公式分割成較小部分,並重複使用這些部分,正如在上一節中所做的那樣,我們將 App.OnStart 中的 Set/Collect 陳述式變更為 App.Formulas 中的具名公式。 在其他程式設計語言中,可重複使用的部分通常稱為副程式或使用者定義的函數。 您可以將具名公式可以視為沒有參數和副作用的使用者定義函數簡單形式。

在任何地方使用命名公式

在先前的範例中,我們使用具名公式做為 App.OnStart 的取代部分。 不過,您可以使用這些公式來取代應用程式中任何位置的計算。

例如,醫院緊急回應範例解決方案的其中一個畫面在 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
    };

App.OnStart 中的大部分 Set 呼叫遷移至 App.Formulas 中的具名公式時,我們已將 ParamFacility 擷取為先前的具名公式。

只有在需要值時,才會計算命名公式。 如果使用 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 變數。

使用畫布元件

畫布元件最常用於建立可以像控制項一樣放置在畫布上的 UI 控制項。 您也可以使用元件而不將其放入 UI 中,以使用自訂輸出屬性執行計算,做為具名公式的替代方法。 畫布元件很容易在具有元件程式庫的應用程式之間共用,而且與具名公式不同,這些元件完全受支援。 不過,設定和使用起來比具名公式要困難。

若要分割邏輯:

  1. 在 Power Apps Studio 中,切換至樹狀檢視中的元件索引標籤。
  2. 建立新元件。
  3. 屬性窗格中,打開存取應用程式範圍
  4. 新增自訂屬性。
  5. 屬性類型設為輸出,並視需要設定資料類型
  6. 選取 建立
  7. 在畫面頂端公式列旁邊的屬性選擇器中,選取新的屬性。
  8. 為要分割和重複使用的邏輯撰寫公式。

若要使用邏輯:

  1. 切換到樹狀檢視中的畫面索引標籤。
  2. 插入窗格中,展開自訂並插入元件。
  3. 若要使用屬性計算值,請使用 ComponentName.PropertyName

將選取與隱藏控制項一起用於命令式邏輯

使用命令式邏輯可以透過 SetCollect 修改狀態、透過 Notify 通知使用者、透過 NavigateLaunch 瀏覽至其他畫面或應用程式,以及透過 PatchSubmitFormRemoveIf 將值寫入或資料庫。

具名公式和畫布元件自訂輸出屬性不支援命令式邏輯。 分割命令式邏輯的常見方式是使用隱藏控制項的 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)
    );

若要將此邏輯分割成多個部分,可以將分割部分放在單獨的按鈕控制項上,並從原始控制項中選取它們:

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 函數在不同的應用程式之間瀏覽,以及傳遞所需的內容。

醫院緊急回應範例解決方案中就使用了這種方法。 不同的應用程式會管理整體應用程式的每個主要區域。 這些應用程式透過每個應用程式在其啟動畫面上顯示的元件程式庫共用通用切換表單:

在行動電話上執行的醫院緊急回應範例解決方案畫布應用程式螢幕擷取畫面,顯示切換表單畫布元件。

當使用者選取區域時,元件會使用有關可用應用程式以及哪些應用程式在裝載該元件的中繼資料。 如果此應用程式中有所需的畫面 (即 ThisItem.Screen 不是空白),則進行 Navigate 呼叫。 但要是所需的畫面是在不同的應用程式中 (即 ThisItem.PowerAppID 不是空白),則會將 Launch 函數與目標的 App 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 函數讀取的參數將狀態傳遞至目標應用程式。

包含自訂頁面的模型導向應用程式

區段也可以實作為自訂頁面。 自訂頁面會當做有模型導向應用程式容器供導覽之用的迷你畫布應用程式。

注意

是否能請您告知您偏好的慣用文件語言? 請填寫問卷。 (請注意,本問卷為英文版)

完成問卷大約需要七分鐘。 本問卷將不會收集個人資料 (隱私權聲明)。