Windows Phone 8.1 - 在 gridview 上使用图片库图像进行数据虚拟化 [英] Windows Phone 8.1 - Data virtualization with pictures library images on gridview
问题描述
我正在构建一个 Windows Phone 8.1 应用程序,它要求我在 GridView 中显示图片库中的所有图像.我构建了一个名为 VirtualList 的类,它是一个支持 IncrementalLoading 的列表,并且我已将图片库中的所有图像添加到该列表中.当图像数量减少(少于 80 张照片)时,一切正常,但当照片超过 80 张时,应用程序会由于 OutOfMemoryException 关闭.我想目前没有显示的项目没有保存在内存中,或者是吗?出于我的目的,我应该继续使用增量加载,还是应该切换到随机访问数据虚拟化?如果我应该切换到随机访问数据虚拟化,您能否提供一个有关如何实现的示例?
I'm building a Windows Phone 8.1 app which requires me to display all images in the pictures library in a GridView. I have built a class named VirtualList which is a list that supports IncrementalLoading, and I have added all the images from pictures library to that list. When there are a reduced number of images (less than 80 photos), everything works fine, but when there are more than 80 photos, the app shuts down due to an OutOfMemoryException. I suppose that the items that aren't displayed at the moment are not kept in memory, or are they? For my purpose, should I continue using incremental loading, or should I switch to random access data virtualization? If I should switch to random access data virtualization, could you provide me with an example about how to implement that?
我的代码如下:
VirtualList.cs
VirtualList.cs
class VirtualList : List<Windows.UI.Xaml.Media.ImageSource>, ISupportIncrementalLoading
{
private IReadOnlyList<StorageFile> photos;
public VirtualList(IReadOnlyList<StorageFile> files) : base()
{
photos = files;
}
public bool HasMoreItems
{
get
{
return this.Count < photos.Count;
}
}
public Windows.Foundation.IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
return LoadMoreItemsAwaitable(count).AsAsyncOperation<LoadMoreItemsResult>();
}
private async Task<LoadMoreItemsResult> LoadMoreItemsAwaitable(uint count)
{
for (int i = Count; i < Count + count; i++)
{
using (var fileStream = await photos[i].OpenAsync(FileAccessMode.Read))
{
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
this.Add(bitmapImage);
}
}
return new LoadMoreItemsResult { Count = count };
}
}
XAML 代码 (MainPage.xaml):
XAML code (MainPage.xaml):
<GridView x:Name="photosGrid" Height="392" Width="400" ItemsSource="{Binding}" Margin="0,0,-0.333,0" SelectionMode="Multiple" Background="Black">
<GridView.ItemTemplate>
<DataTemplate>
<Image Width="90" Height="90" Margin="5" Source="{Binding}" Stretch="UniformToFill"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
MainPage.xaml.cs 代码
MainPage.xaml.cs code
//This code is inside OnNavigatedTo method
var files = await KnownFolders.CameraRoll.GetFilesAsync();
VirtualList imageList = new VirtualList(files);
photosGrid.DataContext = imageList;
推荐答案
除了 Kevin 的反馈,我建议使用 GetThumbnailAsync()
而不是将完整大小的图像拉入内存.
In addition to Kevin's feedback, I recommend using GetThumbnailAsync()
instead of pulling the full size image into memory.
您可以考虑的另一件事是使用转换器,以便仅在调用绑定时加载图像缩略图,然后您可以使用 延迟渲染在 ItemTemplate(延迟渲染是一个很好的改进方式大/长列表的性能)
Another thing you can consider is using a Converter so that the image thumbnail only gets loaded when the binding is called, then you can use Deferred Rendering on the ItemTemplate (Deferred Rendering is a great way to improve the performance of large/long lists)
这是我的缩略图转换器之一:
Here is one of my ThumbnailConverters:
public class ThumbnailToBitmapImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (DesignMode.DesignModeEnabled)
return "images/VideoFileIcon.png";
var fileName = (string) value;
if (string.IsNullOrEmpty(fileName))
return "";
return GetThumbnailImage(fileName);
}
private async Task<BitmapImage> GetThumbnailImage(string fileName)
{
try
{
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName)
.AsTask().ConfigureAwait(false);
var thumbnail = await file.GetScaledImageAsThumbnailAsync(ThumbnailMode.ListView, 90, ThumbnailOptions.UseCurrentScale)
.AsTask().ConfigureAwait(false);
var bmi = new BitmapImage();
bmi.SetSource(thumbnail);
return bmi;
}
catch (Exception ex)
{
await new MessageDialog(ex.Message).ShowAsync();
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
这篇关于Windows Phone 8.1 - 在 gridview 上使用图片库图像进行数据虚拟化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!