WP8.1 RT:数据绑定(远程)图像减缓应用程序

时间:2016-03-20 10:41:13

标签: data-binding windows-phone-8.1 winrt-xaml

背景

我正在使用WP8.1 / WP10移动应用程序,该应用程序可与我在这里使用的本地设备配合使用。此本地设备通过ASP.NET Web APi提供json和图像。我的应用程序进行Web调用以获取信息并向用户显示信息。非常简单的设置。

我的流程如下:用户启动应用。该应用程序找到了#webservice'与UPNP在网络上。当它发生时,它会交换令牌,我们就可以开始调用Web服务了。我抓住了包含标题,副标题和图像的对象列表。图像uri就像:

192.168.1.x:8080/getImage/?uri=someremoteimageurihere.

我的设备会下载这些图像并将它们返回给应用程序(我需要它以这种方式工作以用于此设备的其他用途)。

为了保持用户界面流畅,我在我显示的列表中使用虚拟化,用户可以在没有任何延迟的情况下滚动列表。到现在为止还挺好。只有一个问题:

我的问题

我的问题在于listview模板中的图片。当UI响应时,手机不断下载图像,尤其是当用户从项目#300滚动到项目#1时。您会看到它将图像从#299一直下载到#1。问题是用户正在查看列表中的#1,并且所有图像都需要一分钟左右才能下载,它从#299变为#1。

我想知道如何更好地控制这些图像的加载。在下载这些图片时,我的应用程序似乎没有多少时间用于其他"任务,例如所有其他对web api的调用似乎都要等到屏幕上的图像加载(这没有锁定ui线程!)。所以基本上如果我导航到设置弹出窗口 - 设置只会在加载一批图像后加载。

我有什么方法可以在单个后台线程上加载这些图像吗?只要图像的绑定不优先于任何其他图像,最终用户的延迟是可以接受的。

这个问题不是关于:

  • 在工作时锁定UI线程
  • 帮助绑定数据
  • 缓存策略

感谢您的见解!

3 个答案:

答案 0 :(得分:1)

阶段性功能会解决您的问题吗? Phasing是{x:Bind}的一个特性,它与从ListViewBase派生的控件一起使用,并逐步处理项目模板以进行数据绑定。在渲染列表项时,ListViewBase会在进入下一阶段之前为视图中的所有项呈现单个阶段。渲染工作以时间切片的批次执行,以便在滚动列表时,可以重新评估所需的工作,而不对不再可见的项目执行。 https://msdn.microsoft.com/en-us/windows/uwp/xaml-platform/x-phase-attribute

答案 1 :(得分:1)

您应该在列表视图上尝试随机数据访问数据虚拟化:

随机访问数据虚拟化允许从数据集中的任意点加载。使用随机访问数据虚拟化的ListView,用于查看一百万个项目的集合,可以加载项目100,000 - 100,050。如果用户然后移动到列表的开头,则控件加载项目1-50。滚动条的拇指始终指示ListView包含一百万个项目。滚动条拇指的位置与可见项目在集合的整个数据集中的位置有关。这种类型的数据虚拟化可以显着降低集合的内存要求和加载时间。要启用它,您需要编写一个数据源类,按需获取数据并管理本地缓存并实现这些接口。

https://msdn.microsoft.com/en-us/windows/uwp/debug-test-perf/listview-and-gridview-data-optimization#random-access-data-virtualization

答案 2 :(得分:0)

您可以尝试直接绑定到下载的图像(作为ImageSource资源),而不是使用服务器Uri:因此您拥有在后台自己的代码中下载这些图像并使其可用的所有控件您的ViewModel作为图像集合。

您可以尝试该代码:

public async void GetImage(Uri url) 
{ 
    HttpClient client = new HttpClient(); 
    HttpResponseMessage response = await client.GetAsync(url); 
    byte[] img = response.Content.ReadAsByteArray(); 
    InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream(); 

    DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)); 
    writer.WriteBytes(img); 

    await writer.StoreAsync(); 

    BitmapImage bi = new BitmapImage(); 
    bi.SetSource(randomAccessStream);

    image1.Source = bi; 
}

如果有帮助,请标记为已回答:)