如何解决xamarin表单列表中的内存问题
我已经做了一个简单的项目,以研究Xamarin.Forms应用程序中的性能问题。
对于经典的主从结构,我有两个嵌套列表。根据MVVM模式,我为ViewModel类实现了INotifyPropertyChanged接口,并为列表使用了ObservableCollection。 在主视图中,我有两个标准ListView,第一个(主)绑定到主集合,第二个(详细信息)绑定到主列表中所选项目的详细信息集合。两者都有CachingStrategy =“ RecycleElement”。
运行UWP应用程序时,可以在Visual Studio的诊断工具中查看应用程序的内存使用情况。 当选择的主人列表的元素,细节列表呈现和使用的内存长大了,当选择的主人列表项的变化,细节列表redrowed与各自的项目和使用的内存长大了,另外如果有较少的项目要显示,如果再次选择先前的母版项目,则用过的内存将再次增长。每次母版列表中选定项目更改并刷新详细信息列表时,使用的内存都会增加而不会减少。似乎用于呈现详细信息列表项的对象不会被GC收集。
我认为它的作用太明显了,没有人会注意到它,但是测试项目非常少,所有视图模型都继承自MvvmLight ViewModelBase类,所有属性都使用Set方法,并且所有列表属性类型都是ObservableCollection,唯一自定义代码用于初始加载。 我认为我犯了一个看不见的错误。
在视图模型和视图代码下方
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
this.Load();
}
private RelayCommand _reloadCommand;
public RelayCommand ReloadCommand { get { return _reloadCommand ?? (_reloadCommand = new RelayCommand(this.Load)); } }
private ObservableCollection<ItemViewModel> _items;
public ObservableCollection<ItemViewModel> Items { get { return _items; } set { this.Set(ref _items,value); } }
private ItemViewModel _selectedItem;
public ItemViewModel SelectedItem { get { return _selectedItem; } set { this.Set(ref _selectedItem,value); } }
private SubitemViewModel _selectedSubitem;
public SubitemViewModel SelectedSubitem { get { return _selectedSubitem; } set { this.Set(ref _selectedSubitem,value); } }
private void Load()
{
int[] ranges = { 15,10,5,20 };
this.Items = new ObservableCollection<ItemViewModel>(
from i in Enumerable.Range(1,15)
select new ItemViewModel()
{
Label = $"Item {i}",Items = new ObservableCollection<SubitemViewModel>(from s in Enumerable.Range(1,ranges[i % 4] )
select new SubitemViewModel() { Label = $"Subitem {i}.{s}" })
});
}
}
ItemViewModel.cs
public class ItemViewModel : ViewModelBase
{
private string _label;
public string Label { get { return _label; } set { this.Set(ref _label,value); } }
private ObservableCollection<SubitemViewModel> _items;
public ObservableCollection<SubitemViewModel> Items { get { return _items; } set { this.Set(ref _items,value); } }
}
SubItemViewModel.cs
public class SubitemViewModel : ViewModelBase
{
private string _label;
public string Label { get { return _label; } set { this.Set(ref _label,value); } }
}
MainView.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:App1.ViewModel"
x:Class="App1.MainPage">
<StackLayout>
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Masters" />
<Label Grid.Row="0" Grid.Column="1" Text="Details" />
<ListView Grid.Column="0" Grid.Row="1"
ItemsSource="{Binding Items}"
CachingStrategy="RecycleElement"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:ItemViewModel">
<ViewCell>
<ViewCell.View>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Label}" />
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Grid.Column="1" Grid.Row="1"
ItemsSource="{Binding SelectedItem.Items}"
SelectedItem="{Binding SelectedSubitem,Mode=TwoWay}"
CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:SubitemViewModel">
<ViewCell>
<ViewCell.View>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Label}" />
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackLayout>
</ContentPage>
完整的测试项目可以在这里下载:MemoryTest.zip
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。