Xây dựng các ứng dụng canvas lớn và phức tạp

Hầu hết các bài viết trong phần tài liệu này đề cập đến hiệu suất thời gian chạy của ứng dụng theo kinh nghiệm của những người sử dụng chúng. Bài viết này trình bày về hiệu suất của ứng dụng theo kinh nghiệm của những người tạo ra chúng.

Khi các ứng dụng trở nên lớn hơn và phức tạp hơn, Power Apps Studio cần tải và quản lý số lượng lớn hơn các điều khiển, công thức và nguồn dữ liệu, tất cả đều có sự phụ thuộc lẫn nhau tăng theo cấp số nhân. Power Apps Studio có thể mất nhiều thời gian hơn để tải và các tính năng như IntelliSense và mã màu có thể bị trễ. Sử dụng các đề xuất sau để làm việc tốt hơn với các ứng dụng lớn và phức tạp trong Power Apps Studio. Chúng cũng có thể giúp cải thiện hiệu suất thời gian chạy của ứng dụng của bạn.

Các ví dụ trong bài viết này sử dụng giải pháp mẫu Ứng phó khẩn cấp tại bệnh viện.

Sử dụng App.Formulas thay vì App.OnStart

Mẹo

Bạn có thể sử dụng Với hàm và thuộc tính đầu ra tùy chỉnh của thành phần canvas thay thế cho các công thức được đặt tên.

Cách tốt nhất để giảm thời gian tải cho cả Power Apps Studio và ứng dụng của bạn là thay thế việc khởi tạo biến và bộ sưu tập trong App.OnStart bằng các công thức được đặt tên trong App.Formulas.

Hãy xem ví dụ sau sử dụng 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
    );
);

Vì chúng là một chuỗi các câu lệnh nên ứng dụng của bạn phải đánh giá các ĐặtThu thập các lệnh gọi này theo thứ tự trước nó có thể hiển thị màn hình đầu tiên, khiến ứng dụng tải chậm hơn. Và vì toàn bộ App.OnStart phải được xem xét tổng thể, giữ nguyên thứ tự và tổng hợp các lỗi trước khi trả về kết quả cuối cùng nên công thức rất phức tạp cho Power Apps Studio để phân tích.

Có một cách tốt hơn. Thay vào đó, hãy sử dụng App.Formulas và xác định các biến cũng như tập hợp này dưới dạng công thức được đặt tên, như trong ví dụ sau.

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

Sự thay đổi này có vẻ nhỏ nhưng có thể có tác động rất lớn. Vì mỗi công thức được đặt tên độc lập với các công thức khác nên Power Apps Studio có thể phân tích chúng một cách độc lập, chia nhỏ App.OnStart lớn thành các phần nhỏ một cách hiệu quả. Chúng tôi đã thấy Power Apps Studio thời gian tải giảm tới 80% chỉ với thay đổi này.

Ứng dụng của bạn cũng tải nhanh hơn vì không phải đánh giá các công thức này cho đến khi cần kết quả. Màn hình đầu tiên của ứng dụng được hiển thị ngay lập tức.

Không thể sử dụng công thức được đặt tên trong mọi trường hợp vì bạn không thể sửa đổi hoặc sử dụng chúng bằng Set. Một số tình huống yêu cầu sử dụng biến trạng thái có thể sửa đổi được. Set là lựa chọn hoàn hảo cho những tình huống này và bạn nên tiếp tục sử dụng nó. Tuy nhiên, thường thì bạn đang sử dụng các biến toàn cục trong OnStart để thiết lập các giá trị tĩnh không thay đổi. Trong những trường hợp đó, công thức được đặt tên là lựa chọn tốt hơn.

Vì các công thức được đặt tên là bất biến nên tiền tố var (viết tắt của "variable") làm quy ước đặt tên không còn phù hợp nữa. Chúng tôi không thay đổi tên trong ví dụ này vì nó sẽ yêu cầu thay đổi phần còn lại của ứng dụng để khớp.

Thật hấp dẫn khi đặt một công thức được đặt tên trong App.OnStart, nhưng đừng làm vậy. Họ không thuộc về nơi đó. Là một Thuộc tính hành viOn, App.OnStart đánh giá từng câu lệnh của nó theo thứ tự, tạo các biến toàn cục và nói chuyện với cơ sở dữ liệu chỉ một lần, khi ứng dụng được tải. Công thức được đặt tên là công thức xác định cách tính toán một cái gì đó bất cứ khi nào cần và luôn đúng. Chính bản chất công thức này cho phép chúng độc lập và cho phép ứng dụng tải xong trước khi chúng được đánh giá.

Chia nhỏ các công thức dài

App.OnStart là một trong những kẻ phạm tội nặng nhất đối với các công thức dài và chắc chắn bạn nên bắt đầu từ đâu, nhưng đó không phải là trường hợp duy nhất.

Nghiên cứu của chúng tôi đã chỉ ra rằng gần như tất cả các ứng dụng có thời gian tải lâu Power Apps Studio đều có ít nhất một công thức dài hơn 256.000 ký tự. Một số ứng dụng có thời gian tải lâu nhất có công thức hơn 1 triệu ký tự. Những công thức từ lâu đã gây căng thẳng đáng kể Power Apps Studio.

Tệ hơn nữa, việc sao chép và dán một điều khiển có công thức dài sẽ sao chép công thức đó trong thuộc tính của điều khiển mà không nhận ra được. Power Apps được mô phỏng theo Excel, trong đó phổ biến có nhiều bản sao của một công thức. Tuy nhiên, công thức trong Excel bị giới hạn ở một biểu thức và giới hạn ở 8.000 ký tự. Power Apps các công thức có thể phát triển lâu hơn nhiều khi đưa vào logic mệnh lệnh và toán tử xâu chuỗi (; hoặc ;;, tùy thuộc vào ngôn ngữ).

Giải pháp chung là chia các công thức dài thành các phần nhỏ hơn và sử dụng lại các phần đó, như chúng ta đã làm trong phần trước khi thay đổi câu lệnh Set/Collect in App.OnStart đến các công thức được đặt tên trong App.Formulas. Trong các ngôn ngữ lập trình khác, các phần có thể sử dụng lại thường được gọi là chương trình con hoặc hàm do người dùng xác định. Bạn có thể coi các công thức được đặt tên là một dạng hàm đơn giản do người dùng xác định không có tham số hoặc tác dụng phụ.

Sử dụng công thức được đặt tên ở mọi nơi

Trong ví dụ trước, chúng tôi đã sử dụng các công thức được đặt tên để thay thế cho App.OnStart. Tuy nhiên, bạn có thể sử dụng chúng để thay thế phép tính ở bất kỳ đâu trong ứng dụng.

Ví dụ: một trong các màn hình trong giải pháp mẫu Ứng phó khẩn cấp tại bệnh viện bao gồm logic này trong 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
    }
); 

Công thức này có thể được chia thành một tập hợp các công thức được đặt tên. Nó cũng làm cho công thức dễ đọc hơn.

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

Chúng tôi đã trích xuất ParamFacility dưới dạng công thức được đặt tên trước đó khi chúng tôi di chuyển hầu hết các lệnh gọi Set từ App.OnStart đến các công thức được đặt tên trong App.Formulas.

Các công thức được đặt tên chỉ được đánh giá khi cần đến giá trị của chúng. Nếu mục đích ban đầu của việc sử dụng Screen.OnVisible là trì hoãn công việc cho đến khi màn hình hiển thị thì công việc vẫn được trì hoãn dưới dạng công thức có tên chung trong Công thức ứng dụng.

Sử dụng chức năng Với

Bạn cũng có thể sử dụng hàm With trong công thức để phân tách logic. Tạo một bản ghi trong tham số đầu tiên với các giá trị bạn muốn sử dụng làm trường, sau đó sử dụng các trường đó trong tham số thứ hai để tính giá trị trả về từ Với. Ví dụ: ví dụ trước có thể được viết dưới dạng một công thức được đặt tên:

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

Một nhược điểm của việc sử dụng Với cách này là MyFacility không thể sử dụng MyRegion vì chúng được định nghĩa giống nhau Với hàm, một vấn đề không xảy ra với các công thức được đặt tên. Một giải pháp là lồng Với các hàm và sử dụng từ khóa As để đặt tên bản ghi cho mỗi hàm nhằm giúp truy cập dễ dàng cho tất cả các biến Với .

Sử dụng các thành phần canvas

Các thành phần canvas thường được sử dụng nhiều nhất để tạo điều khiển giao diện người dùng có thể được đặt trên canvas giống như điều khiển. Bạn cũng có thể sử dụng chúng mà không cần đặt chúng trong giao diện người dùng để thực hiện các phép tính với các thuộc tính đầu ra tùy chỉnh thay thế cho các công thức được đặt tên. Các thành phần canvas dễ dàng chia sẻ trên các ứng dụng bằng thư viện thành phần và không giống như các công thức được đặt tên, chúng được hỗ trợ đầy đủ. Tuy nhiên, chúng khó định cấu hình và sử dụng hơn các công thức được đặt tên.

Để phân chia logic:

  1. Trong Power Apps Studio, hãy chuyển sang tab Thành phần trong Chế độ xem dạng cây.
  2. Tạo thành phần mới.
  3. Trong ngăn Thuộc tính, hãy bật Truy cập phạm vi ứng dụng.
  4. Thêm thuộc tính tùy chỉnh.
  5. Đặt Loại thuộc tính thành Đầu raLoại dữ liệu nếu thích hợp.
  6. Chọn Tạo.
  7. Trong bộ chọn thuộc tính bên cạnh thanh công thức ở đầu màn hình, hãy chọn thuộc tính mới.
  8. Viết công thức logic để phân chia và tái sử dụng.

Để sử dụng logic:

  1. Chuyển sang tab Màn hình trong Chế độ xem dạng cây.
  2. Trong ngăn Chèn, mở rộng Tùy chỉnh và chèn thành phần của bạn.
  3. Để tính giá trị với thuộc tính, hãy sử dụng ComponentName.PropertyName.

Sử dụng Chọn với điều khiển ẩn cho logic mệnh lệnh

Logic mệnh lệnh được sử dụng để sửa đổi trạng thái bằng ĐặtThu thập, thông báo cho người dùng bằng Thông báo, điều hướng đến một màn hình hoặc ứng dụng khác bằng Điều hướngKhởi chạy và ghi các giá trị vào cơ sở dữ liệu bằng Patch, SubmitForm hoặc RemoveIf.

Công thức được đặt tên và thuộc tính đầu ra tùy chỉnh của thành phần canvas không hỗ trợ logic mệnh lệnh. Một cách phổ biến để phân chia logic mệnh lệnh là sử dụng thuộc tính OnSelect của một điều khiển ẩn.

  1. Thêm điều khiển Nút vào màn hình.
  2. Đặt thuộc tính OnSelect thành logic mệnh lệnh mà bạn muốn thực thi.
  3. Đặt thuộc tính Hiển thị thành sai vì người dùng không cần phải xem hoặc tương tác với nó.
  4. Gọi Select( Button ) khi bạn muốn thực thi logic mệnh lệnh.

Ví dụ: một trong các màn hình trong mẫu của chúng tôi có thuộc tính OnSelect sau trên điều khiển Button . (Ví dụ đơn giản này chỉ nhằm mục đích minh họa. Thông thường, bạn sẽ chỉ sử dụng kỹ thuật này cho các công thức dài hơn.)

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

Để chia logic này thành nhiều phần, chúng ta có thể đặt các phần vào các nút điều khiển Nút riêng biệt và Chọn chúng từ bản gốc:

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

Kỹ thuật này chỉ hoạt động trên cùng một màn hình. Các kỹ thuật khác phức tạp hơn một chút sẽ hoạt động trên nhiều màn hình, chẳng hạn như sử dụng Chuyển đổi điều khiển, cài đặt OnCheck theo logic bạn muốn chạy và đặt Mặc định thành biến toàn cục rồi chuyển đổi biến toàn cục bằng Set( global, true ); Set( global, false ) tại thời điểm bạn muốn chạy logic.

Trong ví dụ này, một số phân tách logic đã được thực hiện. Nhận xét đề cập rằng "Các hành động tiếp theo có thể được tìm thấy trong OnSuccess." Sự kiện này chạy logic mệnh lệnh sau khi bản ghi được gửi thành công, một giải pháp dành riêng cho hàm SubmitForm .

Phân vùng ứng dụng

Một số ứng dụng phát triển lên tới hàng nghìn điều khiển và hàng trăm nguồn dữ liệu, điều này làm chậm Power Apps Studio. Giống như các công thức dài, các ứng dụng lớn có thể được chia thành các phần nhỏ hơn để phối hợp với nhau nhằm tạo ra một trải nghiệm duy nhất cho người dùng.

Các ứng dụng canvas riêng biệt

Một cách tiếp cận là triển khai các phần trong ứng dụng canvas riêng biệt và sử dụng chức năng Khởi chạy để điều hướng giữa các ứng dụng riêng biệt và chuyển ngữ cảnh cần thiết.

Cách tiếp cận này đã được sử dụng trong giải pháp mẫu Ứng phó khẩn cấp tại bệnh viện. Các ứng dụng riêng biệt quản lý từng lĩnh vực chính của ứng dụng tổng thể. Các ứng dụng chia sẻ một thành phần tổng đài chung thông qua thư viện thành phần mà mỗi ứng dụng hiển thị trên màn hình khởi động của nó:

Ảnh chụp màn hình của ứng dụng canvas Giải pháp mẫu ứng phó khẩn cấp của bệnh viện đang chạy trên điện thoại, hiển thị thành phần canvas của tổng đài.

Khi người dùng chọn một khu vực, thành phần sẽ sử dụng siêu dữ liệu về các ứng dụng có sẵn và ứng dụng nào đang lưu trữ thành phần đó. Nếu màn hình mong muốn có trong ứng dụng này (nghĩa là ThisItem.Screen không trống), thì a Điều hướng cuộc gọi được thực hiện. Nhưng nếu màn hình mong muốn nằm trong một ứng dụng khác (nghĩa là ThisItem.PowerAppID không trống), thì a Khởi chạy hàm được sử dụng với ID ứng dụng của mục tiêu và ngữ cảnh BaseID:

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

Trạng thái trong ứng dụng gốc sẽ bị mất khi một ứng dụng khác được khởi chạy. Hãy nhớ lưu mọi trạng thái trước khi gọi hàm Khởi chạy . Ghi nó vào cơ sở dữ liệu, gọi SaveData hoặc chuyển trạng thái tới ứng dụng đích với các tham số được đọc bằng Param chức năng.

Ứng dụng dựa trên mô hình với các trang tùy chỉnh

Các phần cũng có thể được triển khai dưới dạng trang tùy chỉnh. Các trang tùy chỉnh hoạt động như một ứng dụng canvas nhỏ với vùng chứa ứng dụng dựa trên mô hình để điều hướng.

Lưu ý

Bạn có thể cho chúng tôi biết bạn thích dùng ngôn ngữ nào cho tài liệu không? Làm một cuộc khảo sát ngắn. (xin lưu ý, khảo sát này bằng tiếng Anh)

Cuộc khảo sát sẽ mất khoảng bảy phút. Không có dữ liệu cá nhân nào được thu thập (điều khoản về quyền riêng tư).