我有一个小型网络应用程序,用于在网络和移动设备之间发送文本 - 我想为这个网络应用程序创建一个移动应用程序,并决定使用Xamarin,而不是学习Java和Swift。我买了课程并学会了如何使用Xamarin.Forms和我构建了我的第一个Alpha版本(已经将它发布到Play商店,而App Store版本正处于评论进程中)。
所有开发进度在模拟器上都没有问题,但是一旦我将应用程序下载到我的Nexus 6P(这是一部超级手机) - 在应用程序的各个部分之间移动后,应用程序停止了。我调试它,发现它因为OutOfMemoryException而关闭。该应用程序只有很少的部分与ListView(我意识到ListView的问题,以某种方式使应用程序停止运行 - 虽然它在模拟器上运行得很好)。
我的ViewModels从服务器读取数据(使用HttpClient)并创建绑定到视图的ObservableCollection。我的问题是ListView,它解决了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>
图标是非常小的png文件。这个列表并不大,我不认为一个小的ListView应该抛出这样的异常。这有什么不对?我该如何解决这个问题?
我尝试删除图标并发生同样的问题,我尝试将图标从图像更改为FontAwesome图标,但应用程序停止非常快。我甚至试图使用ChacheImages插件但没有任何帮助。
有什么建议吗?
谢谢, 赛福
答案 0 :(得分:1)
您提到的关键部分是在浏览应用的不同部分后发生这种情况。这意味着你有一个由导航触发的内存泄漏。
一个常见原因是订阅页面上的事件,并且在导航代码不断创建新页面实例时,永远不会取消订阅或以其他方式将整个页面保留在内存中。 如果不查看所有代码,就很难确切地说出问题所在。
另请注意,您的XAML过于复杂。您应该始终努力保持控制嵌套尽可能低。然而,这里有两个框架,两个网格和堆栈布局,全部嵌套。对于您的应用效果,这是糟糕。请考虑简化您的布局。有很多技术可以实现这一目标。只要你可以,使用一个简单的AbsoluteLayout并根据需要按比例调整控件的大小,以显示你的数据。