在我的应用程序中,用户使用像书本一样的枢轴,他翻转枢轴项目,直到他击中最后一个,然后我删除现有的枢轴项目并加载新项目。这只需将Pivot.ItemsSource
属性指向新的项集合即可完成。
我注意到加班时内存消耗增加并且永远不会降低。似乎Pivot的VisualTree没有收集垃圾。
我已经创建了一个示例应用程序来演示问题(这是一个WP8应用程序):
重现的步骤:
多次单击“加载更多”按钮。
(一次加载100件物品当然不是我真实的 应用程序,但它清楚地演示了内存 消费每次都越来越高,即使导航回来也不会被清除)
我会感激任何降低内存的提示或建议,就像它的方式一样,如果应用程序以这种方式使用足够长的时间,应用程序将不可避免地崩溃。
MainPage.xaml中:
...
<HyperlinkButton NavigateUri="/Page1.xaml">
Page1
</HyperlinkButton>
...
MainPage.xaml.cs中:
//...
public MainPage()
{
InitializeComponent();
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(2);
timer.Tick += delegate
{
Debug.WriteLine("{0:f} MB, {1:f} MB",
DeviceStatus.ApplicationCurrentMemoryUsage/(1024.0*1024),
DeviceStatus.ApplicationPeakMemoryUsage/(1024.0*1024));
};
timer.Start();
}
//...
的Page1.xaml:
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" />
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" />
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<phone:Pivot x:Name="pivot1" ItemsSource="{Binding Items}">
<!--Pivot item one-->
<phone:Pivot.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
<Button Click="Load_More">Load More</Button>
</StackPanel>
</Grid>
</Grid>
Page1.xaml.cs:
public partial class Page1 : PhoneApplicationPage, INotifyPropertyChanged
{
private List<int> _items;
public List<int> Items
{
get
{
if (_items == null)
{
_items = new List<int>();
}
return _items;
}
set
{
_items = value;
RaisePropertyChanged("Items");
}
}
public Page1()
{
InitializeComponent();
DataContext = this;
}
private void Load_More(object sender, RoutedEventArgs e)
{
var lst = new List<int>();
//100 new items just for demonstration, in reality i won't have more than 6 new items
for (int i = 0; i < 100; i++)
{
lst.Add(i);
}
pivot1.SelectedIndex = 0;
Items=lst;
}
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string property)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(property));
}
}
~Page1()
{
Debug.WriteLine("Page1 GC");
}
}
答案 0 :(得分:2)
似乎Pivot控件泄漏,正如使用Panorama控件所示。 用这个替换你的堆栈面板(我没有更改控件的名称)不会泄漏。 (记忆得到回收约50兆)
<StackPanel>
<Button Click="Load_More">Load More</Button>
<phone:Panorama x:Name="pivot1" ItemsSource="{Binding Items}">
<phone:PanoramaItem></phone:PanoramaItem>
</phone:Panorama>
</StackPanel>
答案 1 :(得分:1)
一种解决方法是继续重复使用相同的项目集合,而不是创建新的集合。当您需要更改它时,清除该集合,然后重新填充它。该集合可以驻留在App全局空间中,例如:
public partial class App : Application
{
public static List<int> GlobalList;
...
}
在MainPage构造函数中初始化它,然后通过App.GlobalList
引用它。
答案 2 :(得分:1)
也许你可以尝试这个解决方案:Windows Phone 8: LongListSelector Memory Leak
尝试在关闭页面之前清除这些依赖项属性。
尝试使用OservableCollection<T>
代替List<T>
来绑定Itemsource
。将List<T>
绑定到Itemsource
可能会因WPF设计而导致内存泄漏。
A memory leak may occur when you use data binding in Windows Presentation Foundation