Appropriate use of sequential and concurrent approach
While writing actions we can follow two different approaches. Depending on the scenario any of the following approaches can be chosen.
1. Sequential Approach
In this, all the actions should be written in a series like shown below.
Each action is triggered only when the previous one is completed. It is useful in cases, where the coming action depends on the outcome of the previous action. The image below illustrates the flow of actions.
In this, all actions are wrapped in a function name concurrent as shown below:
As the name concurrent itself explains, all the actions will run concurrently. This function can be used where any of the functions are not interdependent. The common place to use concurrent function is at onStart() action of an App. It can reduce the load time drastically if we are working with large data sets. The image below illustrates the flow of actions.
Keynote: - Do not use Concurrent function if actions are interdependent.
Performance difference between both ApproachesThe comparison shown below is calculated on data with more than 5000 entries in total.
In the above image Sequential and concurrent are two buttons which calculate the request time of a particular query. Below the buttons, the calculated time is shown. By studying the difference, we can imagine how the Performance of the App can be drastically changed just by a single concurrent function if applied correctly.
Controls Optimization and Dependency
Before proceeding, we should be aware of the fact that more than 500 controls on a single screen can cause performance degradation. So, make sure that you do not create 500 different controls like gallery control, text input, label, etc on a single screen. Refer to the documentation here for more details.
For optimization of the App, controls should be minimized wherever possible. In the below example we will be replacing 5 button controls with one gallery control and one button control, that will repeat within the gallery.
The 5 buttons control shown above are normal buttons that we usually create. Those 5 button controls can be replaced with one gallery control and 1 button control. When we are creating 5 individual buttons then the number of controls is 5. But when we replace 5 button controls with 1 gallery control and 1 button control, it reduces the number of controls from 5 to 2. This trick is effective in reducing the number of controls over a single screen.In the gallery control shown above we have added a collection of buttons in its Items property as shown below:
Dynamic data can also be added in items according to the scenario. This trick can be used whenever we want to restrict controls in our app. Restricting the number of controls in the app can optimize the app’s performance.
ReusabilityA Component is an excellent example when it comes to reusability. We can make a custom component and use it in our App according to the need. Below is an example of a custom component used as a header.
Here we have a simple example of a component. In this, we are using a label control (lblheader) and an image control (img). Components can be very useful where the same control is being used repeatedly. Our example component above has 2 controls, but when we add it to the screen it will be treated as a single control as shown below:
As we can see in the above image, the component is treated as a single control (Header_Component). But we created it with two different controls which are image control and label control as explained above. When any change is being made in a component, it reflects the changes everywhere we are using the component. This can save time if the component is being used several times in the app. Learn more about components here.
Use of Delay output property in input field.DelayOutput is a property of the text input field. Default it is set to false. Normally if we are making any search request in the gallery or query in the data set it is made for each letter we type. But suppose, we have a large data set, and we make a normal query through the input field. The query will be made for each letter we type which can lead to performance degradation.
We can use the DelayOutput property by going into the advanced section of input field and setting it to true, which is set to false by default. Now a query will only be made once pause while typing. This trick can make the App look more responsive and lag free.
We should be keeping an eye on the dependency also. If not, it can lead to performance degradation. Let us study the example below.
In above example, colour for red label is defined in the same screen it exists.
But for the purple label, color is inherited from a button (SquentialBtn) present in a different screen as shown in the above image.
Everything looks fine until we know the following fact, Power Apps renders all the controls and data of the screen currently in use. When we are inheriting color from other screen Power Apps will load all the controls in that screen also, which can lead to unnecessary performance degradation within the App. Also, one other very common scenario is that where form control in one screen is attached to a gallery control in a different screen. Try to avoid such scenarios if possible.
Best Practices: - We can declare global variables at the start of the app and use them anywhere in the App. With this trick only controls under screen getting used will be rendered, hence increasing the performance of the App. Below is the example for declaring a global variable.
In the above image, we can see that a variable (ThemeColor) is made. It is declared in the OnStart property of the app. That means everything declared here will be processed at the start of the app. If anything is getting used in multiple screens, then best practice is that it should be initialized as a variable in the onStart of the app and then use it anywhere in the app without any issue of control dependency.
Data Connection Queries
This trick is helpful where we are going to use a gallery and having data connectors in it. Suppose the data we are rendering in a gallery control is coming from a SharePoint list. Instead of connecting the SharePoint list directly in the Items property of the gallery control, we should first load the data from the list in a collection. We can immensely improve the performance of the Power App using this method.
Collection can be made at OnStart of the App or OnVisible property of the screen. If we initialize the collection at onStart of the app then the data will only be refreshed at the beginning of the app start. On the other hand, if collection is initialized in the OnVisible property of the screen then it will be refreshed every time the screen gets toggled.
Collection can be made simply by writing the code shown below:
In this, Client is the name given to the collection and ‘Client Lookup’ is the list present in SharePoint. Now you can use a collection called Client in your gallery control.
Note: If other people are making changes to the SharePoint list while another user is working in your gallery control, they will not see the changes unless you provide a mechanism to refresh your collection in some form or fashion. One option that can be applied is by giving a refresh icon somewhere on the screen that will clear collect the collection again from the SharePoint list.
First Filter VS Lookup
The filter function is not delegable and will not return accurate results if our SharePoint list contains data over a particular delegation limit. Refer to the documentation here for more details about delegation.
Limitations/Disadvantages of using the First filter:
- In the image below, a delegation warning can be seen clearly.
- Filter returns table in the result.
- While using the first filter, Power App will load all the data in the gallery and then a query will be made. Suppose we made a query on large data set, and the required result was found in the 50th row, but it will continue to query the whole data set (up to 500 if it has been set to default). Suppose the first item is beyond the 500th row then we will not get any result. You can change the default limit of 500 to 2000 in the app settings.
Considering the disadvantages, one must be careful while using First Filter. All these disadvantages lead to the use of an alternate method, which is Lookup.
In the image below, LookUp is applied to a collection name ClientColl and getting data starting with letter A. By using LookUp we can overcome limitations faced in First Filter option.
Consider a scenario where we are fetching data from Info collection which has three columns ID, Title and Modified. We can fetch the data individually for each column or reduce our lines of code as follows. In the three images below, you can see we are fetching data individually for each column.
By studying three of the above images, it is observed that most of the formula is repeating itself. There is nothing wrong with this too, but a line of code written can be reduced drastically if we are using a lot of data from the same list or collection. Below is an example of how we can implement improvements.
By setting the repeating formula as variable (InfoShort), we can now use this variable in our formula. Below is the implementation. First, we set our variable InfoShort as shown below:
Then we utilise this variable for setting the text property of label as shown below.
Visual and experience Optimization
Use of Spinner
When we load a big amount of data from any source, a lag or latency can be seen. The latency can leave the end user in frustration and can cause a bad experience. By using a spinner, this issue can be tackled. Steps are listed below on how a spinner can be implemented.
- As shown in the below image, set a variable to true at the start of the app. In my case variable name is IsLoading. Then after making all the queries, set IsLoading to false. By doing this we will give a visual representation of spinner loading while our data load operations are being performed.
Note: If you are using the concurrent function, the variable IsLoading should be set outside of it.
2.We have used a label with which we have cover the whole screen as shown below.
3.Give some background colour to the label so that it looks a bit transparent. This will give a kind of blurry effect to the spinner.
4.Set visible property of the label to IsLoading as shown below.
Doing this, label will only be visible when it is set to true (defined in 1st step).
5.Now insert an image in the middle of the screen and set the spinner of your choice. Set visible property of image to IsLoading, same as step 4.
Spinner will be seen when data is being loaded in the app.
Spinner must be used in every possible action where there can be a time delay for a user to interact. You can refer to this free site called loading.io which provides a bunch of free spinners to get you going. Adding a spinner to an app will provide a better experience for the end user.
Written By- Tanish Bawa
(Software Developer Trainee)
Written By- Tanish Bawa
(Software Developer Intern)
Peer Reviewed By- Jasjit Chopra
Peer Reviewed By- Jasjit Chopra
Graphics Designed By- Sanika Sanaye
(Creative Design Director)
Graphics Designed By- Sanika Sanaye
(Creative Graphic Designer Trainee)