During data binding, the busy indicator freezes. This is not a problem with the MAUI ActivityIndicator, however. See the attached video
I created a repo here to reproduce the issue: https://github.com/kklose23/busyindicator-freezing
Note: I know there's ways to make the data binding in that repo more efficient. I just wanted a good example.
Hello Kevin,
That part is interesting indeed, I suspect it has to do with the fact that the ActivityIndicator is a native android control not as subject to the .NET UI thread.
It might help to understand that the ActivityIndicator and the RadBusyIndicator are fundamentally different controls.
Here's a very rudimentary flowchart:
The advantage to one over the other comes down to preference. If you want the same consistency of appearance, color, and behavior across all the platforms, then the RadBusyIndicator is the choice. If you don't care about those things and ore okay with the want the native platform's appearance, then the ActivityIndicator might be better.
As to your question on whether or not the RadBusyIndicator has to run the on the UI thread? It must, because .NET MAUI requires all UI elements to be executed on the UI thread. Even simply adding items to an ObservableCollection that is bound to the UI thread will still force marshalling to the main thread.
What you could to help mitigate UI thread interferences is to also do the item generation n a task and return those results to the UI thread when done.you can also use an ObservableRangeCollection instead of ObservableCollection so that you only need to perform a single AddRange operation (instead of 300 different/expensive Add operations).
For example:
public ObservableRangeCollection<string> Items { get; set; }
[RelayCommand]
async Task ReloadAsync()
{
IsBusy = true;
await Task.Delay(2000);
var newItems = await GetDataAsync(300);
Items.AddRange(newItems);
IsBusy = false;
}
Task<IEnumerable<string>> GetDataAsync(int count)
{
var data = Enumerable.Range(0, count).Select(i => $"{i}");
return Task.FromResult(data);
}
If you would like to continue discussing this with the team, please open a Technical Support ticket (we're currently having this conversation int he public Feedback Portal, which is for folks to track Bug Reports and Feature requests). The same team that handles Feedback Portal items will also be assisting you in the Support Ticket, too.
Regards,
Lance | Manager Technical Support
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.
Hey Lance,
The problem identified isn't something we've done in our main project. That was just a result of me throwing together an inefficient UI thread operation to reproduce the problem.
However, I was wondering if the RadBusyIndicator animation has to run on the UI thread? Since the ActivityMonitor is able to keep animating during the item generation, I assume there must be a way to do it for the RadBusyIndicator as well.
Hello Kevin,
Thank you for the GIF. It looks like the busy indicator is spinning just fine for the 2 seconds of Task.Delay... but then the UI thread is hanging when the app starts adding items to the CollectionView.
This is indicative that your code is hanging the UI thread. The only reason you notice it is because the RadBusyIndicator is using the UI thread to animate and stops spinning when the thread is hung processing something else.
Looking at the debug output, there is some heavy GC occurring
The item generation code itself looks waaaay too simple to be causing UI hangs, even with the other considerations (debugger, emulator, etc).
Telerik Support isn't equipped to assist you with deep dives into performance (it's out of scope), however I did take a trip around the project to see if something stood out
I revisited the MainPage UI layout and there is indeed a major problem there. You're using a StackLayout as a parent of a UI virtualized control. This is an issue that Microsoft strongly warns you about throughout their docs, here are just a couple
We also try to give advice to avoid it, but you will not find this in the RadBusyIndicator's documentation because it is not relevant to the control.
Let me just give you the "bottom line" so that you can avoid problems like this in the future... here are 2 easy rules to follow to avoid this problem in the future
Note: If you are stuck and must use a conflicting parent element, the only way to avoid the above issues is if you give the UI virtualized control hard boundaries (ex. set a HeightRequest="500").
To prove this outcome, I have updated your code so that to the following and opened a Pull Request. see the updated MainPage.xaml for the changes. See Re 1637719 by LanceMcCarthy · Pull Request #1 · kklose23/busyindicator-freezing.
I also updated Telerik.UI.for.Maui to 6.6.0 while I was in there. It is not relevant to today's issue, you just get the following improvements => Telerik UI for .NET MAUI (v6.6.0) Release Notes.
Regards,
Lance | Manager Technical Support
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.
Hi Didi,
I downloaded the repo and tested it, but I'm still getting the same result. See the attached gif.
Hello Kevin,
When working with the busy indicator you do not have to add the UI components inside the busy content. We have a sample integration example here: https://docs.telerik.com/devtools/maui/controls/busyindicator/integrate-with-listview
Here is the relevant code with the changes:
<ContentPage ...>
<Grid>
<VerticalStackLayout>
<Button Text="Load"
Command="{Binding ReloadCommand}" />
<CollectionView ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
<!-- Instead, you can put the RadBusyIndicator on top of the contentTemplate
Also notice how we are also binding to the IsVisible property, this will prevent blocking input gestures -->
<telerik:RadBusyIndicator IsBusy="{Binding IsBusy}"
IsVisible="{Binding IsBusy}"
AnimationType="Animation2"
AnimationContentHeightRequest="100"
AnimationContentWidthRequest="100"
AnimationContentColor="Black"
VerticalOptions="Center"
HorizontalOptions="Center"
BackgroundColor="#AAFFFFFF"
x:Name="RadBusyIndicator" />
</Grid>
</ContentPage>
My colleague Lance forked the repo and applied the changes: https://github.com/LanceMcCarthy/busyindicator-freezing
Test this and let me know the results.
Regards,
Didi
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.