【译】高用户响应的图片加载器

[高用户响应的图片加载器通过在后台加载图片可以让Windows Phone 7的UI线程保持高用户响应]

当在资源比较紧的平台上写应用时,平衡界面上的好与功能速度的快往往不是一件容易的事。理想情况下,按照一般的思路来编程往往可以“恰好工作”(也就是所谓的坑爹货<译者注:好吧,原文是pit of success>),就仅仅是“恰好”而已。但是有时候需要应用变得NB一点,就要有一定的选择了。这就是我最近手上的工程了,这是可以提供一个对于Windows Phone 7来说专注于性能优化的可选方案,机器性能(PhonePerformance)就是所有需要考虑的问题。

注意
这篇文章中所有的东西适用于最新的(内部的)Windows Phone 7版本(Windows Phone 7 builds),不保证适用于公测版(public Beta bits)。当然,我是希望在测试版上也能运行,但是我没有做过测试。虽然这样似乎有一点点不完善,但是团队(译者注:估计是Microsoft)已经在9月16号承认了将发布最终版本的开发工具(译者注:估计以后不会有更新的测试版了,所以基本应该在测试版上能跑),所以我就在这里抛砖引玉一下下了。:)

首先,我来演示一下怎么用LowProfileImageLoader类(以后会再撰文讲DeferredLoadListBox类,这也是可以下载的例子里的一部分,只是现在我还不想直接讲这个)。LowProfileImageLoader就是用来处理一种特殊的场景:同时从网上加载很多的图片。这是再常见不过的情形了,想像一下社交媒体的情形,所有用户的内容边上都有一个小图片。为了更进一步说明,我创建了“Image Loading”应用示例贴在下面,运行一下这个例子,等待它从网上加载用户列表(以及启动两个按钮),然后选择“default”(左边)或者“performance”(右边)场景,接着看屏幕上横向移动的小蓝点的变化:
keep-a-low-profile-1
提示
:我现在讨论的东西是建立在使用真机前提上的。虽然桌面系统上跑模拟器进行开发是非常理想的,但是应用的性能在模拟器上可以产生非常显著的变化。模拟器用来写新代码和调bug是非常好的,但是性能方面的工作还是应该尽可能的在真机上做。

在那行字(译者注:或许是“IMAGE LOADING”)下面的ProgressBar元件(element)的IsIndeterminate属性被设置成了true,它会一直播放动画。ProgressBar的动画完全是在UI线程上运行的,虽然这对于实际的应用来说不是一个很好选择,但是这样做的确可以成为很好的测试工具! 在这里, 我用它(译者注:ProgressBar运行在UI线程上这个事实)来指示UI线程的执行情况,这样可以考查应用对用户输入及更新的响应程度。如果小蓝点可以很平滑的飘动,则UI线程执行流畅(译者注:则响应度很高);如果小蓝点出现跳动或者完全都停止动画了,则应用就失去响应了(译者注:UI线程被卡死,则屏幕不能更新,出现未响应状态,Windows用户应该懂的)。

从例子的“default”那边的测试中可以看到,ItemsControl当中放置了个WrapPanel(实际上,这是我的<译者注:可能是作者自己封装的>BalancedWrapPanel)。ItemsPanel里包含了两百来个网上的小图片(48*48)(如果你很好奇,那是我Twitter上的关注者<译者注:Twitter,tter,er……我们都懂,把代码改成微博的关注者或者人人上的好友吧,如果这些货提供了接口>) ,加载它们可以让应用挂上比较明显的较长的一段时间。时间延迟开销的前半部分仅仅是把列表(译者注:图片或者图片容器)放到容器(译者注:ItemControl或者WrapPanel)中,后半部分则是在下载和处理图片(几乎是在UI线程上进行)的花费。

为了避免出现一段时间不能产生响应,例子的“performance”那边使用了LowProfileImageLoader。虽然绑定列表的初始化开销和之前是一样的,但是使用LowProfileImageLoader可以使UI线程很快开始响应。但是明显的副作用就是图片加载更慢了,但是实际上ProgressBar上的点整个图片加载过程中都在活动,这说明UI线程没有像先使用默认场景(译者注:“default”那边)那样挂了。可以这么说:LowProfileImageLoader用图像加载速度换取了应用的响应性能。

LowProfileImageLoader的工作方式很直接:创建工作线程,然后尽可能的把工作放到那里去。一旦当设置了SourceUri附加属性(attached property),Uri就会送到工作线程的队列里等待处理。同样的,当异步响应来到时,依然放到工作线程的队列中等待处理。与此同时,工作线程在它的(三个)队列上搜寻并高效的批量处理以外,还周期性调用Thread.Sleep(1),向系统发送信号让出优先权给其它有工作要做的线程(真正的线程(true thread priorities)优先级是理想的,但是Thread.Priority在Siverlight中是不存在的)。最后,当它(译者注:工作线程)做了很多工作到是时候阻塞UI线程时,工作线程最后就会调用Dispatcher.BeginInvoke在UI线程上来完成填充BitmapImage的操作,因为这个操作(批量处理)只能在UI线程上进行。LowProfileImageLoader把图片的加载尽可能的放到了单独的工作线程中去,这样的效果就是最大的提高了效率,尽可能的不阻塞UI线程使得更少的破坏用户体验。:)

当然,不同的应用和场景是有区别的,所以不保证LowProfileImageLoader在什么时候都可以用到(或者可以说大部分时候)。不过好在比较容易上手,所以如果你的情况与这里有所相关的话,可以亲自试一下。

[点击这里下载编译好的PhonePerformace,示例应用,完整的源码包。]

具体一点来说,以下就是比较典型的情况:

<Image
    Source="{Binding ProfileImageUrl}"
    Width="24"
    Height="24"/>

然后这里是使用LowProfileImageLoader之后的样子:

<Image
    delay:LowProfileImageLoader.UriSource="{Binding ProfileImageUrl}"
    Width="24"
    Height="24"/>

(不要忘了在XAML文件最上面添加正确的XMLNS:)

xmlns:delay="clr-namespace:Delay;assembly=PhonePerformance"

PS – (译者注:与文章技术无关,不用译了)As an added bonus, the first 500 callerswill receive a free (single-purpose, super bare-bones) Twitter API! (NIH disclaimer: I know there are Twitter libraries out there, but I generally avoid third party code because I don’t want to deal with licensing issues. Yeah, it’s a little paranoid, but it helps me sleep better at night – and besides, this was really simple to dash off.) Operators are standing by…

英文原文: http://blogs.msdn.com/b/delay/archive/2010/09/02/keep-a-low-profile-lowprofileimageloader-helps-the-windows-phone-7-ui-thread-stay-responsive-by-loading-images-in-the-background.aspx

转载英文原文:http://www.juwends.com/tech/windows_phone/keep-a-low-profile.html

【译】高用户响应的图片加载器 —— Juwend 
Juwend’s – http://www.juwends.com
笔者水平有限,若有错漏,欢迎指正,可能涉及原文版权,请尽量不要转载,如涉及原文版权问题,请告知,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值