Fresco之强大之余的痛楚

作者: Aegis | 来源:发表于2015-12-18 18:17 被阅读21146次

    开始之前

    如果你有使用的心得,技巧,踩坑经历,希望贡献出来,我会在TODO中慢慢添加(^^)/

    关于Fresco

      Fresco 是一个强大的图片加载组件。
      Fresco 中设计有一个叫做*image pipeline*的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。
      Fresco 中设计有一个叫做*Drawees*模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用。
      Fresco 支持 Android2.3(API level 9) 及其以上系统。
    

    如果你还不知道Fresco是什么?那么建议一定得去了解下: Fresco官方文档 ; 同时, 建议在看文档的时候优先选择阅读英文文档, 因为中文版文档可能有滞后的情况,这样会避免很多不必要的麻烦。另外,当有问题产生时, 建议去其Fresco Github Issues去进行翻阅查找, 此处汇聚了许多Fresco使用和问题的反馈及解答,往往可能会解决你的一些基本疑惑,甚至,你自己Open New Issue亦无不可。

    使用Fresco

    这其实不是我写此文章的目的, 因为关于使用, 官方文档已经足够详细;并且多篇博客已经进行了解读和使用引导,甚至可运行阅读和Demo。
    什么?想在这儿也学习学习,好吧, 人都是懒惰的,何况我们程序员~~!
    那么,我就简单做个收集吧(也不就是Google Or Baidu Or ... 其他搜索引擎):

    如果你觉得你有更好的链接,请推荐哦

    中文文档
        http://www.fresco-cn.org/ ; 如果真心读不懂英文或者不想读, 那么这里,你可以去看看。
    
    导入官方示例
        http://www.cnblogs.com/stay/p/4398432.html; 简单看了下,还不错, 讲的相对详细,我并未细看。因为其实导入和编译项目该是开发的基本功吧,(*^__^*) 嘻嘻……
    
    简单使用
        http://blog.csdn.net/y1scp/article/details/49245535; 非常详细的使用教程了吧,作者还是比较有心的,点个赞。
    
    进阶研究

    1.Fresco源码解析 - 本地编译
    2.Fresco源码解析 - Hierarachy-View-Controller
    3.Fresco源码解析 - DraweeView
    4.Fresco源码解析 - 初始化过程分析
    5.Fresco源码解析 - DataSource怎样存储数据

    这是一个作者的系列博客吧,具体内容还没时间细细品读,但是能坚持写,可见很有耐心。

    ** Update 进阶1: 2015/12/22**

    昨晚闲来无事逛微博, 发现一个0.7.0版本Fresco的源码解析,看了看, 很是不错,在此更新推荐给大家:

    Fresco-Source-Analysis
    目前看到最好的Fresco的源码解读了吧

    Demo

    Kaede

    Fresco-Sample-Usage
    这个算是一个不错的示例项目吧,可以参考不少东西,具体对项目的介绍,自己去看doc,或者简书中Facebook开源的Android图片加载库Fresco的Demo项目也有介绍;

    ** Huqiu Liao **

    fresco-demo-for-gradle
    秋百万作品,绝对精品。 有个图片加载开源的简单对比,用法也很多,非常有参考价值。值得一提的是,貌似中文文档也是秋百万的作品fresco-docs-cn,可以去观摩一下,我不肯定,但是感觉是。

    开源库使用之痛

    Fresco强大,却也并不完美,但一直在更新,所以,不管你考虑使用,都建议持续关注开源库的发展和更新,因为说不定,就会有好消息,让你学习,让你轻松。

    本人是非常欣赏开源作者的各种开源作品,也乐于使用,只是,开源库之初,总有很多不尽如人意的地方,这也是常说的,~

    是的,这才是本文的重点

    本人在新项目中使用Fresco库,非常感谢Facebook~

    实际使用, 就会遇到各种问题,而我之所以写,也只是因为有些问题, 确实值得我们注意, 写下了,防止自己下次再犯, 同时,也给遇到类似问题的一些参考吧:

    一般情况下,直接 Fresco.initialized(context) 初始化后,在布局中进行如下引用

      <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/my_image_view"   
          android:layout_width="130dp" 
          android:layout_height="130dp" 
          fresco:placeholderImage="@drawable/ic_launcher" />
    

    就已经可以应付大部分情况了, 也无需担心其他问题;
    ** 稍等: 吐槽下, 居然宽高基础使用是必须设置具体的dp值的 **

    可是,本人在使用时,偏偏就是用来做相册多选(自作孽,(⊙﹏⊙)b):

    那么问题来了 ,

    首先的问题就是OOM。。。

    额, 这么强大的库也能OOM?
    都知道,多图加载确实好内存,可是,别的三方库是OK的哇,什么情况?

    当然是使用姿势不太对, 是的, 宫格显示就是大图显示, 导致拖动都卡顿, 于是, 做了优化:

      public static void showThumb(Uri uri, SimpleDraweeView draweeView){    
            ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) 
               .setResizeOptions(new ResizeOptions(DensityUtil.dip2px(144), DensityUtil.dip2px(144)))            
                .build();    
    
            DraweeController controller = Fresco.newDraweeControllerBuilder()              
              .setImageRequest(request)            
              .setOldController(draweeView.getController())           
               .setControllerListener(new BaseControllerListener<ImageInfo>())           
               .build();   
           draweeView.setController(controller);
      }
    

    乍一看,好爽,自动替我Resize了图片, 还抽取个方法, 好复用, 好爽,O(∩_∩)O~;
    ** Tip: 如果Resize后还会出现问题,那么可能参数设置的问题了吧,细查下宽高大小之类吧 **

    运行试了试, 咦~ 滑动好顺畅。。。难道就好了?Oh~No, 新问题出现了,

    ** 图片显示不全 (具体表现为显示为纯白色,或纯黑色)**

    什么鬼?
    也是疑惑异常,之前不Resize之前还能显示的,怎么现在反而有些显示不出了?难道是这个方法有什么问题?
    遂查看官方文档Resizing,看完心中大呼: 法克~ 细节,细节, 细节

    U0~EIQSZBP5ELOH$@`EVU%3.png

    人家文档说的很清楚嘛,此方法 **只支持JPG, 只支持JPG, 只支持JPG, **,内心
    此时是崩溃的,心中想, 只支持JPG怎么够用,现在png的,webp的各种格式的怎么办...

    往下顺着看, 好吧, 哈哈, 请允许我窃喜,是的,官方提供了方法来支持更多格式:

    (5LX_1O0V997KM$JL5R_ULR.png

    ** Tip: 此处记得,不是setDownsampleEnabled(true)就可以了,还得调用之前的Resize方法,人家文档也说的很明白了**

    好吧, 也许即使如此,有些人还不知如何设定这个属性呢,其实很简单哇,人家Configuration是可以定义的哇,** 初始化的时候进行定义 **:

    ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)     
         .setDownsampleEnabled(true)        
          .build();
    
    Fresco.initialize(this, config);
    

    嗯, 是的, Fresco和其他图片加载框架一样,也是支持自定义一些Config属性的,支持很多,什么DiskCacheConfig、ImagePipelineConfig、MemoryCacheParams等很多,自行看官方文档进行脑补吧~

    好吧,问题是否解决了呢,本人运行看了看,ok, 之前白屏的地方,图片出来了,滑动看看呢, 还不错哦。

    ** 更多 **

    当然,也还有很多使用上的问题,我会再使用的同时在此继续更新一些,以使自己能温故而知新。

    另外,我是喜欢做好人的, 如果你懒, 那么,当你出现问题,有几个地方你得去瞅瞅咯:

    Fresco Issue 567 这里有一些PNG图片展示的TooManyBitmapsException

    Fresco Issue 84 可以参考看看评论中解决问题的过程

    Fresco Issue 738 不知道怎么设置缓存?可作参考

    本人也单独配置了一份很详细的Config, 大家也可以根据自己的需要进行个性化配置。

    todo 2015/12/18

      此处占坑, 用来总结更多~~
    

    结尾

    很多时候, 知道强大的东西还不够,我们还都会用,会用还不够,甚至还得去研习如何用的更精, 用精对于好多人依然不够, 因为还要知道其原理, 甚至学习和自己构建;

    最后, 本人正在技术探索的路上, 苦于平时工作压力较大, 时间相对较少, 难免写的过程了有疏漏, 甚至更多,若恰好, 你看到了有问题之处, 或者有建议修改, 那么, 请提出来吧, 帮助我进步 , 谢谢~

    相关文章

      网友评论

      • 萌萌的白天:我用楼主的方法 但是不行 后来看了几个例子
        public void showThumb(Uri uri, SimpleDraweeView draweeView){
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
        .setAutoRotateEnabled(true)//是否可以缩放和旋转图片
        .setLocalThumbnailPreviewsEnabled(true)//是否 启动本地图片预览
        .setResizeOptions(new ResizeOptions(PhoneUtils.getWindowWidth(mContext)/8, PhoneUtils.getWindowWidth(mContext)/8))
        .setProgressiveRenderingEnabled(false)//不渲染
        .build();

        DraweeController controller = Fresco.newDraweeControllerBuilder()
        .setImageRequest(request)
        .setOldController(draweeView.getController())
        .setControllerListener(new BaseControllerListener<ImageInfo>())
        .build();
        draweeView.setController(controller);
        }

        我做是一个选择本地相册的图片上传 其中有些机器会出现在勾选图片的时候出现白屏的情况 经过测试 .setAutoRotateEnabled(true)//是否可以缩放和旋转图片 这句话很重要 特别是在本地预览图片的时候就可以解决白屏问题了
      • 蜗牛1:PhotoDraweeView加载时网络不好时没有默认图片,楼主你是怎么做的
        Aegis:不知道你需要的是不是这个:

        <me.relex.photodraweeview.PhotoDraweeView xmlns:android="http://schemas.android.com/apk/res/android&quot;
        xmlns:app="http://schemas.android.com/apk/res-auto&quot;
        android:id="@+id/photo_drawee_view"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:failureImage="@drawable/ic_error"
        app:failureImageScaleType="centerInside"
        app:placeholderImage="@drawable/ic_placeholder"
        app:placeholderImageScaleType="centerCrop"
        app:progressBarAutoRotateInterval="1000"
        app:progressBarImage="@drawable/ic_loading"
        app:progressBarImageScaleType="centerInside"/>
        斗笔王铁柱:对了。
        还要在xml中指定加载失败后提示重试的图片

        fresco:retryImage="@drawable/retrying"
        fresco:retryImageScaleType="centerCrop"
        斗笔王铁柱:AbstractDraweeController controller = Fresco.newDraweeControllerBuilder()
        .setTapToRetryEnabled(true);//加载失败时是否允许重试
        mSimpleDraweeView.setController(controller);


        试试看这个?
      • 程序浪:不错 完美的解决了我的疑问
      • 李家十三郎的食色记:如果本地路径的图片URi转化后路径变化(比如有网址出现/,原:A/B/%$37d1219.jpg-->A/B/C/19.jpg)就不显示了,这个怎么解决啊?
      • YoKey:哈哈 确实坑很多
        不过对图片依赖不重的app 目前用fresco还是要慎重点好 包太大了 有4M左右…
      • big_panda:强大
      • 4e34f0b7cdea:嗨,博主,这几天,我在为公司的APP载入fresco框架,但是碰到一个问题,感觉原因是fresco的内存配置这款没有弄好,博主能否让我看看你们的内存缓存这块是如何配置的,。。在下不胜感激。
        4e34f0b7cdea:嗯,明白这几个配置,我目前碰到的问题是APP中浏览了几百张800*800分辨率的图片后,内存就会溢出了,我怀疑是fresco的java层这边有泄露,所以想看看你们的配置,或者说有没有哪里可以在浏览了几百张图片后,将fresco恢复到初始状态。
        Aegis:@4e34f0b7cdea
        final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams(
        MAX_MEMORY_CACHE_SIZE,
        MAX_MEMORY_CACHE_ENTITIES,
        MAX_MEMORY_CACHE_SIZE,
        Integer.MAX_VALUE,
        Integer.MAX_VALUE);

        Supplier<MemoryCacheParams> mSupplierMemoryCacheParams = new Supplier<MemoryCacheParams>() {
        @Override
        public MemoryCacheParams get() {
        return bitmapCacheParams;
        }
        };

        内存缓存配置也就是对MemoryCacheParams的几个参数进行配置.

      本文标题:Fresco之强大之余的痛楚

      本文链接:https://www.haomeiwen.com/subject/eovphttx.html