Android图片加载

老生常谈了,但是还是有很多细节不知道的。先挖个坑,后面慢慢埋~

图片加载框架?

  1. Picasso
  2. Glide
  3. Fresco

Picasso:

Picasso :和Square的网络库一起能发挥最大作用,因为Picasso可以选择将网络请求的缓存部分交给了okhttp实现。

Glide:模仿了Picasso的API,而且在他的基础上加了很多的扩展(比如gif等支持),Glide默认的Bitmap格式是RGB_565,比    Picasso默认的ARGB_8888格式的内存开销要小一半;Picasso缓存的是全尺寸的(只缓存一种),而Glide缓存的是跟ImageView尺寸相同的(即56*56和128*128是两个缓存) 。

FB的图片加载框架Fresco:最大的优势在于5.0以下(最低2.3)的bitmap加载。在5.0以下系统,Fresco将图片放到一个特别的内存区域(Ashmem区)。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。为什么说是5.0以下,因为在5.0以后系统默认就是存储在Ashmem区了。

Fresco性能上的优点
优一:
1、支持webp格式的图片,是Google官方推行的,它的大小比其它格式图片的大小要小一半左右,目前各个大公司都渐入的使用这种图片格式了,比如:Youtube、Gmail、淘宝、QQ空间等都已尝鲜,使用该格式最大的优点就是轻量、省流量、图片加载迅速。而Fresco是通过jni来实现支持WebP格式图片。

优二:
2、5.0以下系统:使用”ashmem”(匿名共享内存)区域存储Bitmap缓存,这样Bitmap对象的创建、释放将永远不会触发GC,关于”ashmem”存储区域,它是一个不在Java堆区的一片存储内存空间,它的管理由Linux内核驱动管理,不必深究,只要知道这块存储区域是别于堆内存之外的一块空间就行了,且这块空间是可以多进程共享的,GC的活动不会影响到它。5.0以上系统,由于内存管理的优化,所以对于5.0以上的系统Fresco将Bitmap缓存直接放到了堆内存中。

关于”ashmem”的存储区域,我们的应用程序并不能像访问堆内存一样直接访问这块内存块,但是也有一些例外,对于Bitmap而言,有一种为”Purgeable Bitmap”可擦除的Bitmap位图是存储在这块内存区域中的,BitmapFactory.Options中有这么一个属性 inPurgeable :

BitmapFactory.Options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
所以通过配置inPurgeable = true这个属性,这样解码出来的Bitmap位图就存储在”ashmem”区域中,之后用到”ashmem”中得图片时,则把这个图片从这个区域中取出来,渲染完毕后则放回这个位置。

既然Fresco中Bitmap缓存在5.0以前是放在”ashmem”中,GC并不会回收它们,且也不会被”ashmeme”内置的清除机制回收它们,所以这样虽然使得在堆中不会造成内存泄露,而在这块区域可能造成内存泄露,Fresco中采取的办法则是使用引用计数的方式,其中有一个SharedReference这个类,这个类中有这么两个方法:addReference()和deleteReference(),通过这两个基本方法来对引用进行计数,一旦计数为零时,则对应的资源将会清除(如:Bitmap.recycle()等),而Fresco为了考虑更容易被我们使用,又提供了一个CloseableReference类,该类可以说是SharedReference类上功能的封装,CloseableReference同时也实现了Cloneable、Closeable接口,它在调用.clone()方法时同时会调用addReference()来增加一个引用计数,在调用.close()方法时同时会调用deleteReference()来删除一个引用计数,所以在使用Fresco的使用,我们都是与CloseableReference类打交道,使用CloseableReference必须遵循以下两条规则:

1、在赋值CloseableReference给新对象的时候,调用.clone()进行赋值

2、在超出作用域范围的时候,必须调用.close(),通常会在finally代码块中调用

void gee() {
CloseableReference<Val> ref = foo();
try {
haa(ref);
} finally {
ref.close();
}
}
遵循这些规则可以有效地防止内存泄漏。

优三:
3、使用了三级缓存:Bitmap缓存+未解码图片缓存+硬盘缓存。其中前两个就是内存缓存,Bitmap缓存根据系统版本不同放在了不同内存区域中,而未解码图片的缓存只在堆内存中,Fresco分了两步做内存缓存,这样做有什么好处呢?第一个好处就如上的第二条,第二个好处是加快图片的加载速度,Fresco的加载图片的流程为:查找Bitmap缓存中是否存在,存在则直接返回Bitmap直接使用,不存在则查找未解码图片的缓存,如果存在则进行Decode成Bitmap然后直接使用并加入Bitmap缓存中,如果未解码图片缓存中查找不到,则进行硬盘缓存的检查,如有,则进行IO、转化、解码等一系列操作,最后成Bitmap供我们直接使用,并把未解码(Encode)的图片加入未解码图片缓存,把Bitmap加入Bitmap缓存中,如硬盘缓存中没有,则进行Network操作下载图片,然后加入到各个缓存中。

既然Fresco使用了三级缓存,而有两级是内存缓存,所以当我们的App在后台时或者在内存低的情况下在onLowMemory()方法中,我们应该手动清除应用的内存缓存,我们可以使用下面的方式:

    ImagePipeline imagePipeline = Fresco.getImagePipeline();
    //清空内存缓存(包括Bitmap缓存和未解码图片的缓存)
    imagePipeline.clearMemoryCaches();
    //清空硬盘缓存,一般在设置界面供用户手动清理
    imagePipeline.clearDiskCaches();

    //同时清理内存缓存和硬盘缓存
    imagePipeline.clearCaches();

3.总结:
Picasso所能实现的功能,Glide都能做,无非是所需的设置不同。但是Picasso体积比起Glide小太多如果项目中网络请求本身用的就是okhttp或者retrofit(本质还是okhttp),那么建议用Picasso,体积会小很多(Square全家桶的干活)。Glide的好处是大型的图片流,比如gif、Video,如果你们是做美拍、爱拍这种视频类应用,建议使用。
Fresco在5.0以下的内存优化非常好,代价就是体积也非常的大,按体积算Fresco>Glide>Picasso
不过在使用起来也有些不便(小建议:他只能用内置的一个ImageView来实现这些功能,用起来比较麻烦,我们通常是根据Fresco自己改改,直接使用他的Bitmap层)

MemoryFile 可以用来测试共享内存

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容