2013年的谷歌I/O已然到来并结束,它让我们对Android的未来发展持有了极大的期待。今年I/O上最令人兴奋的事情是一个称为Volley的库。Volley是一个处理并缓存网络请求的库,目的是将开发人员从在几乎所有的应用中编写相同代码中解救出来。写样板代码从来都是无趣的,且会增加开发者出错的几率。正是处于这种考虑谷歌创造了Volley。
如果你没有看过谷歌I/O上关于Volley的介绍,我建议你先去看一下有个初步了解,然后再继续阅读本文。
其它翻译版本 (1) 加载中在谷歌I/O上的报告中,Ficus Kirpatrick谈了很多Volley是如何助力于加载图像的内容。使用Volley作为图像加载解决方案后你会发现,在它自己处理L2缓存的同时,盒子外它需要但不包括的L1图像缓存。很多人使用诸如通用图像装载器或Square的新Picasso库来处理图像加载;然而,这些库通常只是处理图像加载和缓存。那么,我们如何使用Volley来替代加载和缓存图像呢?首先,让我们看看Volley提供了什么来方便装载,以后我们再了解其他内容。
该ImageLoader类持有一个请求的实例以及一个ImageCache的实现。图像是通过传递URL和一个ImageListener的实例到get()方法来加载的。在那里,ImageLoader检查ImageCache,如果图像不在缓存中就从网络中加载图像。
其它翻译版本 (1) 加载中在你的布局中用这个类替换ImageViews并使用ImageLoader。NetworkImageView的setUrl()方法接受一个字符串URL路径以及一个ImageLoader的实例。然后用ImageLoader的get()方法取回图像的数据。
<com.android.volley.toolbox.NetworkImageView android:id="@+id/twitterUserImage" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_width="40dp" android:layout_height="40dp" android:padding="5dp" />
ImageCache
Volley的ImageCache接口允许你使用你喜欢的L1缓存来实现。不幸的是,Volley的缺点之一是没有缺省的缓存实现。在I/O大会上演示了一段BitmapLruCache的代码段,但是这个库本身不包含任何实现。
ImageCache 接口有两个方法getBitmap(String url)和putBitmap(String url, Bitmap bitmap)。这些桩是足够简单的,他们可以被添加到任何缓存实现中。
其它翻译版本 (1) 加载中在这个例子中,我已经创建了一个简单的APP,它在Twitter中搜索"CapTech",并在列表中显示搜索到的Twitter结果,每一列附带用户名和图片。当你向下滚动屏幕时,列表将自动加载更老的记录,如果需要的话,将从缓存中获取图片。
CapTech
有两个可用的缓存实现方案。推荐的方法是在内存中使用一个LRU缓存。磁盘中的缓存实现我选择使用Jake Wharton写的DiskLruCache。我选择它的原因是它在安卓社区中被广泛的使用,并且有人提供了一个将它的应用程序改造到Volley的用例。使用基于L1的磁盘缓存可能导致I/O阻塞的问题。Volley已经有一个隐含的磁盘L2缓存。磁盘的L1缓存被包含在内因为我原来不知道Volley是怎么出来图片的缓存请求的。
其它翻译版本 (1) 加载中实现方案的主要模块如下:
RequestManager维护RequestQueue的引用。Volley使用 RequestQueue处理Twitter数据和图片加载的请求。
这个模块和图片加载不直接相关,但是它代表了你怎样扩展Request类用于处理JSON解析。它将用于Twitter的GET请求和TwitterData对象。
在内存缓存实现方案中这是一个基础的“最近最少使用”方案。它很快并且不阻塞I/O,是推荐的方法。
其它翻译版本 (1) 加载中DiskLruImageCache是对DiskLruCache的位图实现。它从DiskLruCache中添加和查询位图,并处理缓存实例。磁盘缓存会阻塞I/O。
ImageCacheManager持有了我们的 ImageCache和Volley ImageLoader的引用。在 ImageCacheManager中你将注意到一件事情我们将URL字符串的hashCode()值作为键放入缓存中。这样做是因为URL的一些字符不能作为缓存的键。
这个适配器很简单。唯一需要注意到事是我们在这里实现了Volley的 Listener 和 ErrorListener 接口,并且把这个适配器作为Listener参数传递给了NetworkImageView 的 setUrl(String string , Listener listener, ErrorListener errorListener) 方法。这个适配器包含了一些在滚动时自动加载旧tweets的一些代码。
Tweet tweet = mData.get(position); if(tweet != null){ viewHolder.twitterUserImage.setImageUrl(tweet.getUserImageUrl(), ImageCacheManager.getInstance().getImageLoader()); viewHolder.userNameTextView.setText("@" + tweet.getUsername()); viewHolder.messageTextView.setText(tweet.getMessage()); viewHolder.tweetTimeTextView.setText(formatDisplayDate(tweet.getCreatedDate())); viewHolder.destinationUrl = tweet.getDestinationUrl(); }
现在,有了以上这些功能组件,图片加载和缓存也就变得容易多了。在开始的时候,程序在MainApplication这个类中初始化了 RequestManager 和 ImageCacheManager 。你可以在MainApplication 中声明你想要的L1缓存,默认是缓存在内存中的。
首次加载时,我们在 MainActivity 中调用了 TwitterManager 并且加载了我们的初始数据。一旦我们接收到了返回的数据,我们就把它传递给BuzzArrayAdapter 并把该适配器设置给我们的ListView。
正如我们从上面的 BuzzArrayAdapter 代码中看到的那样, NetworkImageView 在图片加载的过程中承担了绝大部分的工作,我们只需要将从 ImageCacheManager 中得到的实例传递给我们的image loader即可。
该ImageCacheManager检查我们的LRU缓存的实现,并返回可用的图片。如果图片不在缓存中,它回去网络中获取。
当你滚动ListView的时候,BuzzArrayAdapter 会加载其他的tweets以及对应的图片,并且会重用已经缓存的图片。
尽管Volley的用处很大,速度也快并且很容易实现,但是现在还不是使用它的最好时机,原因如下:
缺少相关的文档和示例The library lacks any documentation or examples.
像缓存组件的一些配置,并不是像我想象的那样具有高可配置性。
正如上面你所看到的那样,基本图片缓存的排除策略实现的很奇怪。引入一个 NoImageCache 也许更加有用,或者让缓存变成可选的,以便满足你需要从网络上获取所有东西的需求。
在开发者社区有很多和Volley相关并且令人振奋的消息。给人的感觉是这个库已经被作为Android API,并且被引入了很长时间了。就像在I/O大会上宣布的新的Location API 那样,Google正在逐步移除掉一些对app开发产生阻碍的东西,以便使开发者的生活更加“美好”。
VolleyImageCacheExample-master.zip
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务