maui
maui copied to clipboard
CarouselView on Android - "Cannot access a disposed object"
Description
On Android, when using a CarouselView and entering and exiting that page a lot of times, sometimes we receive the error: "Cannot access a disposed object" (as seen in the image below).
From the call stack of the exception seems that error is here:
When it calls the UpdateVisualState()
https://github.com/dotnet/maui/blob/f8c60532b1744e74cfa6462ea7021fea137a748f/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs#L286
And here it tries to GetLayoutManager().
https://github.com/dotnet/maui/blob/f8c60532b1744e74cfa6462ea7021fea137a748f/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs#L354
But it's just a guess. Not 100% sure.
This is the code for CarouselView
page:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CarouselViewBugAndroid.CarouselOnePage"
xmlns:local="clr-namespace:CarouselViewBugAndroid"
xmlns:behaviors="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:DataType="local:CarouselOneViewModel">
<ContentPage.Behaviors>
<behaviors:EventToCommandBehavior
x:DataType="local:CarouselOneViewModel"
EventName="Appearing"
Command="{Binding PageAppearingCommand}" />
</ContentPage.Behaviors>
<ContentPage.Resources>
<DataTemplate x:Key="CustomCategoryTemplate" x:DataType="local:CustomCategory">
<Label Text="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="CustomPageTemplate" x:DataType="local:CustomPage">
<VerticalStackLayout>
<Label Text="{Binding Id}"></Label>
<Label Text="{Binding PageName}"></Label>
<Label Text="{Binding PageContent}"></Label>
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="I have "></Span>
<Span Text="{Binding WordsLength}"></Span>
<Span Text=" words."></Span>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Text="{Binding PageContent}"></Label>
<Label Text="{Binding Id}" Margin="0,10,0,0"></Label>
<Label Text="{Binding PageName}"></Label>
<Label Text="{Binding PageContent}"></Label>
<Image
Source="dotnet_bot.png"
HeightRequest="185"
Aspect="AspectFit"
SemanticProperties.Description="dot net bot in a race car number eight" />
<ListView ItemsSource="{Binding Categories}" Margin="0,20,0,0"
ItemTemplate="{StaticResource CustomCategoryTemplate}" />
<Image Margin="0,20,0,0"
Source="dotnet_bot.png"
HeightRequest="185"
Aspect="AspectFit"
SemanticProperties.Description="dot net bot in a race car number eight" />
</VerticalStackLayout>
</DataTemplate>
</ContentPage.Resources>
<ScrollView Margin="10">
<VerticalStackLayout>
<Label Text="Hello" VerticalOptions="Center"
HorizontalOptions="Start" />
<IndicatorView
x:Name="IndicatorView"
IndicatorColor="Yellow"
SelectedIndicatorColor="Red"
HorizontalOptions="Start"
VerticalOptions="Center" />
<CarouselView Margin="20"
IndicatorView="IndicatorView"
Loop="false"
ItemsSource="{Binding Pages}"
ItemTemplate="{StaticResource CustomPageTemplate}" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
This error seems to happen even more where there's a lot of things happening in the ViewModel.
The following video shows the error using the repo provided below. To make it easier to understand, I'm clicking the CarouselOne
button and entering CarouselOnePage
and then using the shortcut Ctrl + Backspace
to go back and doing this a couple of times.
https://github.com/dotnet/maui/assets/26172581/04eabc5c-85db-454c-8388-c75e025d1860
Steps to Reproduce
- Get the repo provided and get the
main
branch. - Start the app on Android.
- Click on the
CarouselOne
button to enterCarouselOnePage
. - Then click to go back but then ASAP try to click the button
CarouselOne
button again. - Do this a couple of times and probably you will found the issue.
Link to public reproduction project repository
https://github.com/BrnPer/CarouselViewBugAndroid.git
Version with bug
8.0.7 SR2
Is this a regression from previous behavior?
No, this is something new
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
Android 12, Android 14 (didn't try in other version)
Did you find any workaround?
After some testing it seems that in the ViewModel not calling Pages.Clear()
in the PageAppearingCommand but doing for example Pages = []
on a page disappearing event solves the issue.
Relevant log output
System.ObjectDisposedException
Message=Cannot access a disposed object.
Object name: 'Microsoft.Maui.Controls.Handlers.Items.MauiCarouselRecyclerView'.
Hitting this as well. Here's a full stack trace.
System.ObjectDisposedException ObjectDisposed_Generic ObjectDisposed_ObjectName_Name, Microsoft.Maui.Controls.Handlers.Items.MauiCarouselRecyclerView
void JniPeerMembers.AssertSelf(IJavaPeerable)
void JniInstanceMethods.InvokeVirtualVoidMethod(string, IJavaPeerable, JniArgumentValue*)
void RecyclerView.RemoveItemDecoration(ItemDecoration)
void MauiCarouselRecyclerView.UpdateItemDecoration()
void MauiCarouselRecyclerView.UpdateItemSpacing()
void MauiRecyclerView<CarouselView, ItemsViewAdapter<CarouselView, IItemsViewSource>, IItemsViewSource>.LayoutPropertyChanged(object sender, PropertyChangedEventArgs propertyChanged)
void WeakNotifyPropertyChangedProxy.OnPropertyChanged(object sender, PropertyChangedEventArgs e)
void BindableObject.OnPropertyChanged(string propertyName)
void BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, bool silent)
void BindableObject.SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity)
void BindableObject.SetValue(BindableProperty property, object value)
void DynamicMarkupExtensionBase.SetValue(object target, object value)+() => { }
void MauiExtensions.DispatchIfRequered(IDispatcher dispatcher, Action action)
void DynamicMarkupExtensionBase.SetValue(object target, object value)
void DynamicMarkupExtensionBase.UpdateValue()
void OnScreenSizeExtensionBase.OnMainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e)
void DeviceDisplayImplementationBase.OnMainDisplayInfoChanged(DisplayInfoChangedEventArgs) x 2
async void Listener.OnOrientationChanged(int)
void Task.ThrowAsync(Exception, SynchronizationContext)+(object state) => { }
void SyncContext.Post(SendOrPostCallback, object)+() => { }
void RunnableImplementor.Run()
void IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
void JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz)
Hello, I had the same problem but I changed my register: Before AddTransient and now AddSingleton It work now
I'm having the same problem and I can't find how to solve it.