Reputation: 297
I have a small web app for sending texts between web and mobile - I wanted to create a mobile apps for this web app and decided to go with Xamarin instead of learning both Java and Swift. I bought courses and learned how yo use Xamarin.Forms and I built my first Alpha version (which already released it to the Play Store and the App Store version is in the Review progress).
All the development progress went very well on the Emulator with no issues, but once I downloaded the app to my Nexus 6P (which is a super phone) - after moving between sections on the app, the app stopped. I debugged it and found that it is closing because of OutOfMemoryException. The app only have very few sections with a ListView (I realized that the issue with the ListView which somehow makes the app stop running - while it is running very well on the emulator).
My ViewModels read the data from the server (using HttpClient) and creates the ObservableCollection which is binded to the views. My issue is with the ListView which makes all the problem with the OutOfMemory:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame HasShadow="False" OutlineColor="White" Padding="10, 10, 10, 20" VerticalOptions="Center">
<Frame.Content>
<Frame OutlineColor="Gray" VerticalOptions="Center">
<Frame.HasShadow>
<OnPlatform x:TypeArguments="x:Boolean" Android="True" WinPhone="True" iOS="False" />
</Frame.HasShadow>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" FontSize="Small"
Text="{Binding Paste.Text}" />
<Grid Grid.Row="1" Padding="0, 20, 0, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ffimageloading:CachedImage x:Name="btnCopy" Grid.Column="0" DownsampleToViewSize="true" Scale="0.8" Source="copy.png">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CopyToClipboardCommand, Source={x:Reference pastesPage}}" CommandParameter="{Binding .}" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
<StackLayout Grid.Column="1">
<ffimageloading:CachedImage x:Name="btnFavourite" DownsampleToViewSize="true"
IsVisible="{Binding ShowFavouriteButton}"
Scale="0.8"
Source="{Binding FavouriteImage}">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.ChangePasteFavouriteCommand, Source={x:Reference pastesPage}}" CommandParameter="{Binding .}" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
<ActivityIndicator IsRunning="{Binding IsFavouriteRunning}"
IsVisible="{Binding IsFavouriteRunning}"
Scale="0.7" Color="Gray" />
</StackLayout>
<StackLayout Grid.Column="2">
<ffimageloading:CachedImage x:Name="btnDelete" DownsampleToViewSize="true"
IsVisible="{Binding ShowDeleteButton}"
Scale="0.8" Source="delete.png">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.DeletePasteCommand, Source={x:Reference pastesPage}}" CommandParameter="{Binding .}" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
<ActivityIndicator IsRunning="{Binding IsDeleteRunning}"
IsVisible="{Binding IsDeleteRunning}"
Scale="0.7" Color="Gray" />
</StackLayout>
<ffimageloading:CachedImage x:Name="btnShare" Grid.Column="3" DownsampleToViewSize="true" Scale="0.8" Source="share.png">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SharePasteCommand, Source={x:Reference pastesPage}}" CommandParameter="{Binding .}" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
</Grid>
</Grid>
</Frame>
</Frame.Content>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
The icons are very small png files. This list is not large and I don't think that a small ListView should throw such an exception. What is wrong here? How can I fix this issue?
I tried to remove the icons and the same issue happen, I tried to change the icons from images to a FontAwesome icons but the app stopped very quickly. I even tried to use the ChacheImages plugin but with no help.
Here is an image of the list that is produced:
Any suggestions?
Thanks, Seif.
Upvotes: 0
Views: 269
Reputation: 2296
The key part you mentioned is that this occurs after moving through the different sections of your app. This implies you have a memory leak somewhere which gets triggered by navigation.
One common cause is subscribing to events on page appear and never unsubscribing or otherwise keeping whole pages in memory while the navigation code keeps creating new page instances. Without looking at all of your code, it's hard to say exactly where the problem is.
Also note that your XAML is way too complex. You should always strive to keep control nesting as low as possible. Yet here you have two frames, two grids and stack layouts, all nested. This is terrible for your app performance. Please consider simplifying your layout. There's numerous techniques to accomplish this. Whenever you can, use a simple AbsoluteLayout and proportionally size the controls as needed to display your data.
Upvotes: 1