My question is very easy. What is the correct point for loading data from service/database in the page or view?
I am using OnAppearing
method:
protected override void OnAppearing()
{
base.OnAppearing();
_ = Task.Run(async () =>
{
await Task.Delay(500);
await LoadData();
});
}
private async Task LoadData()
{
this.Items = await this.LoadDataFromDatabase();
}
Definition of items:
[ObservableProperty]
private ObservableCollection<Product>? _items = null;
The database returns a maximum of 20 items.
I use ScrollView
with HorizontalWrapLayout
and DataTemplate
for items.
DataTemplate:
- Border
- -- Grid with rows
- --- Label
- --- Label
- --- Label
My problem is that the application is not smooth. Flyout menu is not smooth. It seems like UI wait for loading data. Loading data from database takes /- 100ms however displaying data (20 items) on the page takes another 3-4sec. User experience is not very smooth in Release mode. The same result is also in Mobile/Tablet/Virtual devices/Phyical devices.
I also measured the speed of HorizontalWrapLayout:
- Measure: ~10ms
- ArrangeChildren: ~15ms
I have many of these logos in android:
Skipped 363 frames! The application may be doing too much work on its main thread.
What can be wrong? Is it possible that this is MAUI problem? I load the data and the whole display happens automatically via bindable property = Items. What is the correct point of loading data (Constructor in model or OnAppearing or.... )?
- I uses Net7.0 and last version of MAUI => 7.0.52
- Visual Studio 2022 version 17.5 Preview 2
- Android API 33, Android v13 (virtual devices also phyzical devices)
- PC: Intel(R) Core(TM) i9-10850K CPU @ 3.60GHz, 32 GB ram
I am providing more information because my assumption is that the problem is not in weak devices.
Thank you for any advice, recommendations, suggestions, etc.
Edit 1:
Now I noticed a very interesting thing. HorizontalWrapLayoutManager is very fast (I listed the times above). However, Measure and ArrangeChildren are called 128-time to display data. (~10ms ~15ms) * 128 = 3200ms. A very interesting thing is that the widthConstraint parameter for Manager is always the same, but the heightConstraint changes alternately between 1493 and Infinity. Is there any logic why the manager is called 128 times when displaying 8 items?
Edit 2:
I reduced my xaml step by step. After removing each parent view, the recalculation of the Manager is called less times. By removing almost everything, recalculation in the manager is called only 4 times. It also seems that if there is a parent Grid element with Auto size for Column or Row, the number of recalculations increases. I understand the logic of the recalculation, but it causes the display of data to be very slow in the final. Accordint to my logs, methods (Measure and Arrange) on the View inside the Manager cause a final delay when called repeatedly. Would not the solution be to save the data and call these methods only once?
CodePudding user response:
First, I want to point out that I see this:
await Task.Delay(500);
In a question related to performance and speed.
I do not know what you plan to do with this, and why you are doing it. But whatever the reason, please remove that line.
Second, if you are using Android, please make sure you test your performance in release. It may differ in order of magnitudes compared to the performance you see in debug.
If this does not help, try CollectionView, or DataGrid, and see if it will get better.
Edit: Just want to add, you are doing it correctly. I often use OnAppearing for loading and displaying data. (as command in my ViewModels)
CodePudding user response:
My summarization:
I use HorizontalWrapLayout with custom implementation for HorizontalWrapLayoutManager.
I foud out that Manarger is very fast, however ArrangeChildren and Measure are called more times. The number depends on the number of parents and the layout of the screen. The number of calls also affects the auto size in parent's Grids. Repeated recalculation and calls to Measure/ArrangeChildren in HorizontalWrapLayoutManager cause a large delay when displaying data in HorizontalWrapLayout.
I solved the problem by updating the HorizontalWrapLayoutManager. Manager stores the data returned from Measure and Arrange for each child. The first call will be recalculated. In the event that the items, padding, spacing, widthConstraint or other essential values have not changed during subsequent calls, the Manager no longer calls Measure and Arrange for each view, but returns data from the cache.
Small test:
- HorizontalWrapLayoutManager without cache = 128 calls => ~3100ms
- HorizontalWrapLayoutManager with cache = 128 calls => ~100ms
So far, I have not found any problems that would result from the cache. In the future, however, it is not excluded that recalculation will have to occur when other properties of HorizontalWrapLayout are changed.