Android最好用、最强大的图片加载框架:Fresco的简单实用教程
貌似有2个月没写博客了,原因还跟以往一样,忙+懒,其实二者是相辅相成的,忙的时候要想抽点时间也还是有的,但一忙就懒得管工作以外的事情了,一 来二去也就会拖延很久。最近把公司项目中的图片加载框架由Universal-Image-Loader换成了Fresco,感觉有必要做个记录。
一个内容充实的应用,图片是必不可少的。而图片往往体积比较大,从服务器下载图片那肯定是要用异步线程来做的,在UI主线程中尽量不做任何耗时操作 是每个Android开发者应该遵循的准则。你可以自己来写如何加载图片,但多数开发者的能力可能不足以完成一个足够好的图片加载框架,好在网上资源丰 富,已经有好几个开源的图片加载框架供我们选择,它们都能比较好的满足我们的需求,可以让开发者不用太专注于图片的处理。比较有名的有 Universal-Image-Loader、Picasso、Volley,以及今天的主角——Fresco。
要说,我们项目中原来Universal-Image-Loader用的也好好的,没什么问题,但有更好的技术还是要及时跟进的。Fresco是 Facebook发布的一款开源框架,号称是目前最强的Android图片加载库,在内存方面的表现极为优秀,既然有如此信心,那么至少我应该先尝试一 下,若真的好用,就替换掉UIL了。
对于Fresco的一些介绍,就不多说了,如果你感兴趣肯定会到网上找一些相关的资料,建议你到官网查 看:http://frescolib.org/。当然了,国内的大神也对这个网站进行了翻译,如果你英语水平比较捉急,请到http: //fresco-cn.org/来进行观摩,不过还是建议到官网,因为你不知道什么时候会有更新,第三方的文档会不及时。
下面直接来一段代码吧,看过就知道Fresco用起来是多么简单了:
记住,要想在项目中引入Fresco,只需要在Module的build.gradle文件的dependencies中添加一句话
1 compile 'com.facebook.fresco:fresco:0.7.0+'
至于Eclipse的用户,呃,请自己到官网进行观摩,有教程,但你真的还要对Android Studio视而不见继续用Eclipse么……
主Activity代码:
package com.kaelli.frescodemo;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.view.SimpleDraweeView;
public class MainActivity extends Activity {
private SimpleDraweeView mSimpleDraweeView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fresco.initialize(this);
setContentView(R.layout.activity_main);
mSimpleDraweeView = (SimpleDraweeView)findViewById(R.id.simpleDraweeView);
mSimpleDraweeView.setImageURI(Uri.parse("http://f2.topit.me/2/79/0a/1175191760a730a792o.jpg"));
}
}
相对应的布局文件:
XHTML
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:id="@+id/simpleDraweeView"
android:layout_width="match_parent"
android:layout_height="match_parent"
fresco:fadeDuration="300"
fresco:actualImageScaleType="fitCenter"
fresco:placeholderImage="@drawable/image1"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImage="@drawable/image1"
fresco:failureImageScaleType="fitCenter" />
程序的运行截图如下:
FrescoDemo运行图
看得出来,Fresco的一个很大的特点在于,它自定义了一个SimpleDraweeView,而不是直接在ImageView上进行操作。你可 能会觉得这样有些麻烦,毕竟人家UIL是直接用普通的ImageView的,但Facebook这么做是有其道理的。如果你有兴趣,查看一下源码,看得出 来目前SimpleDraweeView是继承自ImageView的,然而很多ImageView的方法已经被@Deprecated掉了,不建议使用,而且其开发人员也表示今后的版本中,Fresco的SimpleDraweeView将会直接继承自View,与ImageView再无关系。
使用Fresco有一些需要注意的地方:
1、一定不要忘了Fresco库的初始化:
Fresco.initialize(this);
通常这一句将在Application的onCreate中是比较合适的,如果只有一个Activity,那么加在Activity里也可以,但要在setContentView之前,也就是要先初始化库,才能完成布局文件的加载。
SimpleDraweeView的width和height属性必须是明确值,而不能直接用wrap_content这种内容填充的数值,当然 有一种情况例外,就是宽度和高度有一个是固定的,然后设置了二者的比例,则另一个可以用wrap_content,其实相当于二者都是固定的。
mSimpleDraweeView.setAspectRatio(1.33f); // 设置宽高比为4:3
3、正常情况下,一个SimpleDraweeView的各种属性,既可以在布局文件里面设置(如上面的代码),也可以在Java代码里设置,作用 是一样的。但既然提到了“正常情况”,那就必然有非正常情况了:当SimpleDraweeView被被一些第三方自定义View包裹的时候,比如最常见 的,一个可下拉刷新的第三方ListView,则此时在布局文件中的一些属性居然是无效的!好吧,根本原因我并没有找到,只能在代码里面设置属性了,仍然 没有任何难度:
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
GenericDraweeHierarchy hierarchy = builder
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.setPlaceholderImage(getResources().getDrawable(R.drawable.image1), ScalingUtils.ScaleType.FIT_CENTER)
.setFailureImage(getResources().getDrawable(R.drawable.image1), ScalingUtils.ScaleType.FIT_CENTER)
.build();
mSimpleDraweeView.setHierarchy(hierarchy);
一般来说,安全起见,还是直接在Java代码里写比较好,布局文件里面只是声明一个SimpleDraweeView就足够了。
4、不要使用那些被@Deprecated的方法,尽管这些方法(如setImageResource或者setImageBitmap)是可用 的,但在以后的版本中也许就作废了。Fresco的建议是,直接用setImageURI的方法来设置图片,即使是本地的图片也用这种方法。
今天只写了Fresco的最基本的用法,实际上可能很多人比较关心它的性能到底有多么出色,那么以后我会用它来跟Universal-Image-Loader还有Picasso进行对比,这样你就能知道,为什么要选择Fresco了。
Android图片加载库对比:Universal-Image-Loader vs Glide vs Fresco vs Picasso几大框架的选择
翻了翻最近的一篇博客,居然是去年10月份的,也就是说半年多没有写点什么了,显然人一旦懒起来,连自己都会吃惊。最近个人生活有很大的变化,当然并不是差的变化,那么工作上、学习上也要变好一点,最简单的,自然是要变得勤快一点,别懒下去了。
对于很多Android App来说,都会有图片加载的需求,毕竟有图片的App才能显得更加多姿多彩。要实现图片加载,其基础的原理并不麻烦,大概有这么几点:
图片应该是异步加载的,从网络上下载图片会是一个比较耗时的过程,如果是在UI主线程里进行,那么ANR肯定无法避免了。任何耗时操作都在异步线程里进行,这是一个Android开发者应有的基本素质。
图片从网上下载完之后,需要在本地进行Bitmap的处理,最重要的就是图片的压缩。这一步是比较难办的,压缩的力度太大,图片的显示效果就会比较差;压缩的不够,那么图片就会占用大量内存,动辄就搞出OOM这种事情来。
最好实现一个自己的缓存策略,即把图片下载到本地memory和disk(其实就是Flash)中,需要保存下来并有一定的策略,这样下次再加载同样的图片的时候,就可以直接在本地加载而不需要去网络下载了,大大提升了加载速度并节省了流量,当然这一步也是比较麻烦的。
实现了以上3点,你就可以做出一个基本的图片加载库了,当然,可能会比较粗糙。实际上呢,网上有大量的图片加载库,而且是开源的,最重要的在于,这 些库都有各自的缓存策略,而且经过了大量开发者的实践考验,都很可靠。其中,比较有名的有:Universal-Image-Loader、 Picasso、Volley、Glide和Fresco,那么到底该如何选择呢?
Universal-Image-Loader
这是一个很早就出现的图片加载框架了,作者是大名鼎鼎的nostra13,UIL使用方便,而且自有多种缓存策略,如最大尺寸先删除、时间最久删除 等,使用它,基本上不需要考虑太多的问题,可以把精力节省下来投入到开发的其他地方。另外,UIL还支持图片下载进度的监听,如果你有特殊需求,则可以在 图片开始下载前、刚开始下载等各个时间段来做一些额外的事情,非常方便。而且UIL可以在View滚动的过程中暂停图片的加载,有利于提升界面的流畅度。 然而,作者前阵子(2015/11/27)宣布不再维护这个项目了,换言之,以后它不会更新了——虽然有可能被其他开发者接手,但考虑到现在图片加载库十 分丰富,有这个兴致的人怕是不多。如果你要开发新项目,可以不考虑UIL了,但如果是一个比较老而又庞大的项目并且使用了UIL,那么倒也不必太着急替换 它,至少目前它还是能很好的完成图片加载任务的。
Picasso
来自于开源界名气很大的Square公司(对,就是那个著名的JakeWharton大神所在的公司),总体来看它比较小巧,但也有着一些自己的特 色。比如,很特别的拥有统计功能,可以知道使用了多少内存、缓存命中如何,另外它本身没有什么缓存策略,而是依赖所用的网络库的缓存策略——嗯,其实就是 依赖了OkHttp了。Picasso使用起来也是比较简单的,不过对于新项目来说,也不是很推荐,原因就在于,Glide比它更优秀,而且使用起来几乎 是一样的……
Glide
来自于bumptech,被Google官方所推荐,甚至在许多Android的原生应用中都采用了Glide来加载图片,可见其受推崇的程度。如果你知道Picasso和Glide的基本使用方法,就会神奇的发现,二者是很相似的:
Java
1
2
3 Picasso.with(context)
.load("image src url")
.into(ImageView);
1
2
3 Glide.with(context)
.load("image src url")
.into(ImageView);
从某种程度上说,Glide可以看作是Picasso的改进版。那么它又有什么独特的优势呢?Glide不仅支持常见的jpg和png格式,还能显 示gif动画,甚至是视频,换言之它已经不仅仅是一个普通的图片加载库了,而是一个多媒体库。另外一个优势是,Glide在内存方面的表现相当出色,首先 它的图片默认格式是RGB565,要比ARGB8888节省更多内存,而且它缓存的不是原始图片,而是缓存了图片的实际大小——比如加载的图片是 19201080的大小,而在你的App中,显示该图片的ImageView大小只有1280720,那么Glide就会很聪明的自动缓存 1280*720大小的图片。
Fresco
这个可以称为是Android平台上目前最为强大的图片加载库了,来源于地球人都知道的Facebook公司。与Glide一样,Fresco也是 支持gif动画显示,而且在内存方面的表现更是无敌。由于将图片放在Ashmem(匿名共享内存)中,大大降低了App的内存占用(因为Ashmem没有 被统计到App的内存使用里),再加上各种神优化,使得Fresco基本上告别了OOM,而且Fresco的图片直接显示为ARGB8888这种最高质量 的级别,即使是在这种高质量的情况下依然保证了比其他库更少的内存占用,不得不佩服Facebook的实力。而且类似于进度监听、缓存策略等,也是应有尽 有,总之作为一个图片加载库,Fresco在功能和性能方面已经趋于完美了。
其他的之Volley
Google官方出品,质量其实也只能算是马马虎虎了,事实上我更愿意把它当成是一款网络库——然而在这个领域它仍然被其他对手碾压,so……就不多说了。
该如何选择图片加载库?
如果你手中的项目比较老旧,而且代码量较大,你又没什么时间去大改,那么继续维持当前的选择是比较稳妥的办法。如果是新上马的项目,那么UIL由于 不再维护、Picasso基本被Glide全方位超越,我推荐使用Glide或Fresco。如果你的App里,图片特别多,而且都是很大、质量很高的图 片,而且你不太在乎App的体积(这可能吗?),那么Fresco就是很好的选择了,而Glide相比较Fresco要轻量一些,而且是Google官方 推荐,所以在多数时候,会是开发者的首选。话说回来,如果你非常在意App的体积,不肯让App多增加多余的1KB,那么,也许自己实现一个图片加载库也 是不错的选择哦,而且能很好的锻炼自己的能力,何乐而不为呢?