【问题标题】:Infinite scrolling WP8 LongListSelector with Images带有图像的无限滚动 WP8 LongListSelector
【发布时间】:2014-12-16 05:25:24
【问题描述】:

我有一个 LongListSelector,我用它来显示一堆像缩略图一样的图像。在滚动(无限滚动场景)时,图像正在下载并且应用程序在图像显示后变慢(即在 LongListSelector 上滚动变慢)时,应用程序再次恢复活力。

我正在使用如下所示的 xaml:

<Image Stretch="UniformToFill" 
      Margin="-3,0,0,0" 
      Source="{Binding video_thumbnail}" 
      Opacity="1" 
      Height="200" Width="480" />

video_thumbnail 是一个字符串。

我应该以这种方式创建图像还是有更好的方法来优化我的代码?

【问题讨论】:

  • 是的,在某些时候您可能会遇到内存不足异常。我无法理解您的问题,您无法显示无限的 LongListSelector,或者您正在寻找显示图像的最佳做法
  • 没有无限的 LongListSelector 工作 - 只是它似乎在滚动后下载图像并且它请求新数据并下载这些图像非常慢 - 所以我只是想知道我是否正在使用无限滚动场景中多张图片的最佳实践
  • 您是绑定到内存中的图像还是磁盘上的文件?
  • 在内存中...uri是一个网址

标签: c# xaml windows-phone-8


【解决方案1】:

我有类似的问题。我已经通过实现我自己的下载图像队列来解决它。一次只下载一张图片,这样你就只有一个线程了。

您可能认为图片下载速度会变慢,但事实并非如此。同时下载所有 5 张图片时,一张一张下载 5 张图片所需的时间相同。我在my own app 中测试过。

这是我的例子。首先,我创建了一个类来存储有关视频的基本信息:缩略图的 url 和缩略图本身为 ImageSource,因此您可以轻松地将其绑定到 XAML 中 ImageSource 属性。

public class VideoItem
{
    public string Url { get; private set; }
    public ImageSource Thumbnail { get; set; }

    public VideoItem(string url)
    {
        this.Url = url;
    }
}

下一个类会将所有视频存储在一个可观察列表中,因此您可以在绑定中使用它。该列表会随着缩略图的下载而增加,一张一张。

public class VideoLibrary
{
    private WebClient thumbnailDownloader = new WebClient();
    private Queue<VideoItem> downloadQueue = new Queue<VideoItem>();
    private bool isBusy = false;

    public ObservableCollection<VideoItem> Videos = new ObservableCollection<VideoItem>();

    public VideoLibrary()
    {
        thumbnailDownloader.OpenReadCompleted += OnThumbnailDownloaded;
    }

    // It will not start downloading process but only add a new video item (without thumbnail) to download queue.
    public void Download(string url)
    {
        downloadQueue.Enqueue(new VideoItem(url)); // Just add to queue.
        CheckQueue();
    }

    // Check whether there are new thumbnails to download. If so, start downloading just one.
    private void CheckQueue()
    {
        if (isBusy) // Stop! Downloading in progress...
            return;

        if (downloadQueue.Count > 0)
        {
            isBusy = true;
            VideoItem item = downloadQueue.Peek();
            thumbnailDownloader.OpenReadAsync(new Uri(item.Url));
        }
    }

    // One thumbnail has been downloaded. We can add it to the list of videos and check the queue again.
    private void OnThumbnailDownloaded(object sender, OpenReadCompletedEventArgs e)
    {
        isBusy = false;

        if (e.Cancelled)
        {
            CheckQueue(); // Just try again.
        }
        else if (e.Error != null)
        {
            downloadQueue.Dequeue(); // Skip this video (thumbnail), check the next one.
            CheckQueue();
        }
        else if (downloadQueue.Count > 0)
        {
            VideoItem item = downloadQueue.Dequeue(); // Remove the video from queue.
            WriteableBitmap bitmap = new WriteableBitmap(null); 
            bitmap.SetSource(e.Result);
            item.Thumbnail = bitmap; // Thumbnail is ready to use.

            Videos.Add(item); // Add to list.

            CheckQueue();
        }
    }
}

【讨论】:

  • 我应该将所有图片下载到独立存储吗?这是一长串项目,从技术上讲可以永远增长......
  • 不,我的意思是本地图片列表。我会在编辑此答案时向您展示我的示例。
【解决方案2】:

this文章:

  • 永远不要将服务器托管的图像直接绑定到控件,因为 Silverlight 运行时将使用 UI 线程(使用 WebClient)从服务器获取该图像,这会使 UI 在一段时间内无响应。

  • 使用后台线程和基于 HttpWebRequest 类的实现以一种有效的方式下载图像数据,最终创建 BitmapImage 并将其设置为源。一个干净的 MVVM 包装器将使您的整个图像管理变得非常容易。

另外,通过Best Practices for Windows Phone development`

  • 将 BitMapCredtiOptions 值设置为 BackGroundCreation。如果 UriSource 已经存在一个缓存图像,这将允许它使用缓存图像。

  • 如果图像尺寸很大,例如由许多手机摄像头拍摄的高分辨率图像,那么在解码图像的所有像素时会消耗相当多的 CPU 处理。如果您知道要渲染的图像帧的大小,则可以使用该信息来设置要解码的像素大小。

  <Image ..>
    <Image.Source> 
         <BitmapImage
             UriSource="{Binding video_thumbnail}"
             CreateOptions="BackgroundCreation"/> 
   </Image.Source> 
 </Image>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多