Windows Phone 8.1 - 在 gridview 上使用图片库图像进行数据虚拟化 [英] Windows Phone 8.1 - Data virtualization with pictures library images on gridview

查看:21
本文介绍了Windows Phone 8.1 - 在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆