• Fresco-Facebook的图片加载框架的使用


    目前常用的开源图片加载框架有:1.Universal-Image-Loader,该项目存在于Github上面https://github.com/nostra13/Android-Universal-Image-Loader

    2.fresco,该项目的中文网站是:http://www.fresco-cn.org/,在Github上面是:https://github.com/facebook/fresco

    之前一直用的是Universal-Image-Loader,改用fresco之后,在有大图展示的页面,能明显感觉到fresco在渲染速度和图片呈现效果上更胜一筹。fresco与Universal-Image-Loader比起来,最直观的几个优点是:
    1.在显示圆形、圆角图片时,不需要另行引入CircleImageView等第三方或者自定义控件;
    2.更容易实现图片View的点击效果;
    3.默认的渐入显示效果;

    下面来说一下fresco的使用:

    1.如果使用的是Android Studio,则需要在build.gradle中引入fresco项目:

    1. dependencies {  
    2. ......  
    3. compile 'com.facebook.fresco:fresco:0.9.0+'  
    4. ......  

    其中0.9.0是fresco的版本;

    2.在程序显示图片之前调用init接口,一般会在Application的onCreate方法中调用Fresco.initialize()方法,该方法有两种传参方式:

    1. /** Initializes Fresco with the default config. */  
    2. public static void initialize(Context context)  
    3.   
    4. /** Initializes Fresco with the specified config. */  
    5. public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig)  


    其中不对ImagePipeline进行配置的话,Fresco将采用默认的配置。ImagePipelineConfig可以进行如下配置:

    1. public ImagePipelineConfig getImagePipelineConfig() {  
    2.     ImagePipelineConfig config = ImagePipelineConfig.newBuilder(App.getAppContext())  
    3.             .setWebpSupportEnabled(true)  
    4.                     /** 
    5.                      * 必须和ImageRequest的ResizeOptions一起使用,作用就是在图片解码时根据ResizeOptions所设的宽高的像素进行解码,这样解码出来可以得到一个更小的Bitmap。ResizeOptions和DownsampleEnabled参数都不影响原图片的大小,影响的是EncodeImage的大小,进而影响Decode出来的Bitmap的大小,ResizeOptions须和此参数结合使用是因为单独使用ResizeOptions的话只支持JPEG图,所以需支持png、jpg、webp需要先设置此参数。 
    6.                      */  
    7.             .setDownsampleEnabled(true)  
    8.                     /** 
    9.                      * 最终影响的是mDownsampleEnabledForNetwork参数。 这个参数的作用是在mDownsampleEnabled为true的情况下,设置是否当这次请求是从网络中加载图片时,来对三级缓存中的编码图片重新改变大小。 
    10.                      */  
    11.             .setResizeAndRotateEnabledForNetwork(true)  
    12.                     /** 
    13.                      * 是否根据不同的平台来构建相应的解码器 
    14.                      */  
    15.             .setDecodeMemoryFileEnabled(true)  
    16.                     /** 
    17.                      * 所加载图片的配置,默认为Bitmap.Config.ARGB_8888 
    18.                      */  
    19.             .setBitmapsConfig(Bitmap.Config config)  
    20.                     /** 
    21.                      * 三级缓存中已解码图片的内存缓存配置 
    22.                      */  
    23.             .setBitmapMemoryCacheParamsSupplier(bitmapCacheParamsSupplier)  
    24.                     /** 
    25.                      * 三级缓存中编码图片的内存缓存 
    26.                      */  
    27.             .setEncodedMemoryCacheParamsSupplier(encodedCacheParamsSupplier)  
    28.                     /** 
    29.                      * 三级缓存中硬盘缓存的配置,默认缓存目录在app自身CacheDir的image_cache目录下 
    30.                      */  
    31.             .setMainDiskCacheConfig(mainDiskCacheConfig)  
    32.                     /** 
    33.                      * 执行各个任务的线程池配置,包括配置执行IO任务、后台任务、优先级低的后台任务、Decode任务的线程池的配置。 
    34.                      */  
    35.             .setExecutorSupplier(executorSupplier)  
    36.                     /** 
    37.                      * 缓存的统计数据追踪器。它是一个接口,提供了各个缓存中图片Hit与Miss的回调方法,通常可以使用它来统计缓存命中率 
    38.                      */  
    39.             .setImageCacheStatsTracker(imageCacheStatsTracker)  
    40.                     /** 
    41.                      * 注册一个内存调节器,它将根据不同的MemoryTrimType回收类型在需要降低内存使用时候进行回收一些内存缓存资源(Bitmap和Encode)。数值越大,表示要回收的资源越多。 
    42.                      */  
    43.             .setMemoryTrimmableRegistry(memoryTrimmableRegistry)  
    44.                     /** 
    45.                      * 网络图片下载请求类 
    46.                      */  
    47.             .setNetworkFetchProducer(networkFetchProducer)  
    48.                     /** 
    49.                      * 渐进式显示网络的JPEG图的配置,不过要使用渐进式显示图片,需要在ImageRequest中显示的设置是否支持渐进式显示:setProgressiveRenderingEnabled(true) 
    50.                      */  
    51.             .setProgressiveJpegConfig(progressiveJpegConfig)  
    52.                     /** 
    53.                      * 小图的硬盘缓存配置,默认是和主硬盘缓存目录是共用的。如果需要把小图和普通图片分开,则需重新配置。 
    54.                      */  
    55.             .setSmallImageDiskCacheConfig(smallImageDiskCacheConfig)  
    56.             .build();  
    57.     return config;  
    58. }  

    这里要介绍一下fresco的三级缓存:Bitmap缓存+编码/未解码图片缓存+硬盘缓存。Fresco的加载图片的流程为:查找Bitmap缓存中是否存在,存在则直接返回Bitmap直接使用,不存在则查找未解码图片的缓存,如果存在则进行Decode成Bitmap然后直接使用并加入Bitmap缓存中,如果未解码图片缓存中查找不到,则进行硬盘缓存的检查,如有,则进行IO、转化、解码等一系列操作,最后成Bitmap供我们直接使用,并把未解码(Encode)的图片加入未解码图片缓存,把Bitmap加入Bitmap缓存中,如硬盘缓存中没有,则进行Network操作下载图片,然后加入到各个缓存中。ImagePipelineConfig及fresco的缓存原理详见:http://blog.csdn.net/u010687392/article/details/50266633

    3.使用com.facebook.drawee.view.SimpleDraweeView替换掉ImageView。SimpleDraweeView可以通过配置实现圆形、圆角、pressed效果、默认图片、加载失败图片等显示效果,在布局中可以如下配置(以圆形效果为例):

    1. <com.facebook.drawee.view.SimpleDraweeView  
    2.     android:id="@+id/iv_user_avatar"  
    3.     android:layout_width="@dimen/common_big_user_portrait_height"  
    4.     android:layout_height="@dimen/common_big_user_portrait_height"  
    5.     android:layout_centerInParent="true"  
    6.     /** 正常图片的ScaleType*/  
    7.     fresco:actualImageScaleType="centerCrop"  
    8.     /**图片加载失败时的图片及其ScaleType*/  
    9.     fresco:failureImage="@drawable/default_user_portrait"  
    10.     fresco:failureImageScaleType="centerCrop"  
    11.     /** 默认图片及其ScaleType*/  
    12.     fresco:placeholderImage="@drawable/default_user_portrait"  
    13.     fresco:placeholderImageScaleType="centerCrop"  
    14.     /**pressed效果,一般是通过布局shape一种色值*/  
    15.     fresco:pressedStateOverlayImage="@drawable/common_circle_image_pressed"  
    16.     /**圆形 */  
    17.     fresco:roundAsCircle="true"  
    18.     />  

    如果是圆角的话,可以在上面的基础上增加如下特殊配置,其中fresco:roundedCornerRadius根据需要具体设置值:

    1. fresco:roundAsCircle="false"  
    2. fresco:roundBottomLeft="true"  
    3. fresco:roundBottomRight="true"  
    4. fresco:roundTopLeft="true"  
    5. fresco:roundTopRight="true"  
    6. fresco:roundedCornerRadius="xdp"  

    然后在代码中,调用如下语句即可显示网络或者本地图片:

    1. String uri = bean.getUrl();  
    2. if (!uri.startsWith("http")) {  
    3.     uri = "file://" + bean.getUrl();  
    4. }  

    如果就是想让view显示默认的图片,则调用语句:

    1. simpleDraweeView.setImageURI(Uri.parse(“”));  

    如果想修改默认的ImageRequest、DraweeController等的配置,则可以在代码中这样配置和显示图片(以显示圆形图片为例):

    1.     public void displayCirclePortraitImage(Context context, String picUrl, SimpleDraweeView iv_pic) {  
    2.         if (iv_pic == null) {  
    3.             return;  
    4.         }  
    5.         Context tempContext = context;  
    6.         if (tempContext == null) {  
    7.             tempContext = App.getAppContext();  
    8.         }  
    9.         if (!StringUtil.isEmpty(picUrl)) {  
    10.             Uri uri = Uri.parse(picUrl);  
    11.             ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)  
    12.                     .setLocalThumbnailPreviewsEnabled(true)  
    13.                     .setAutoRotateEnabled(true)  
    14.                     .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)  
    15.                     .setProgressiveRenderingEnabled(false)  
    16.                     .build();  
    17.             DraweeController controller = Fresco.newDraweeControllerBuilder()  
    18.                     .setImageRequest(request)  
    19.                     .setAutoPlayAnimations(true)  
    20.                     .setOldController(iv_pic.getController())  
    21.                     .build();  
    22.             iv_pic.setController(controller);  
    23.         } else {  
    24.             iv_pic.setImageURI(Uri.parse(""));  
    25.         }  
    26. //        GenericDraweeHierarchy ghy = iv_pic.getHierarchy();  
    27. //        if (ghy == null) {  
    28.             GenericDraweeHierarchyBuilder gbulder = new GenericDraweeHierarchyBuilder(tempContext.getResources());  
    29.             ghy = gbulder.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)  
    30.                     .setPlaceholderImage(tempContext.getResources().getDrawable(R.drawable.default_user_portrait), ScalingUtils.ScaleType.CENTER_CROP)  
    31.                     .setFailureImage(tempContext.getResources().getDrawable(R.drawable.default_user_portrait), ScalingUtils.ScaleType.CENTER_CROP)  
    32.                     .setRoundingParams(RoundingParams.asCircle())  
    33.                     .setPressedStateOverlay(tempContext.getResources().getDrawable(R.drawable.common_circle_image_pressed))  
    34.                     .build();  
    35.             iv_pic.setHierarchy(ghy);  
    36. //        } else {  
    37. //            ghy.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP);  
    38. //            ghy.setRoundingParams(RoundingParams.asCircle());  
    39. //        }  
    40.         float scaleRadio = 1.0f;  
    41.         iv_pic.setAspectRatio(scaleRadio);  
    42.     }  

    如果只想下载图片,不使用SimpleDraweeView控件,则可以通过如下方法:

    1. public void loadImage(Context context, String picUrl, ResizeOptions resizeOptions, BaseBitmapDataSubscriber bitmapDataSubscriber) {  
    2.     if (StringUtil.isEmpty(picUrl)) {  
    3.         return;  
    4.     }  
    5.     Uri uri = Uri.parse(picUrl);  
    6.     ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)  
    7.             .setLocalThumbnailPreviewsEnabled(true)  
    8.             .setAutoRotateEnabled(true)  
    9.             .setResizeOptions(resizeOptions)  
    10.             .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)  
    11.             .setProgressiveRenderingEnabled(false)  
    12.             .build();  
    13.   
    14.     ImagePipeline imagePipeline = Fresco.getImagePipeline();  
    15.     DataSource<CloseableReference<CloseableImage>>  
    16.             dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);  
    17.     dataSource.subscribe(bitmapDataSubscriber, CallerThreadExecutor.getInstance());  
    18. }  

    其中回调接口BaseBitmapDataSubscriber实现如下:

    1. FrescoImageLoader.getInstance().loadImage(ViewSinglePhotoActivity.this, picUrl, resizeOptions, new  
    2.         BaseBitmapDataSubscriber() {  
    3.             @Override  
    4.             protected void onNewResultImpl(Bitmap bitmap) {  
    5.                 ViewSinglePhotoActivity.this.runOnUiThread(new Runnable() {  
    6.                     @Override  
    7.                     public void run() {  
    8.                         loadPb.setVisibility(View.GONE);  
    9.                     }  
    10.                 });  
    11.                 if (bitmap != null && photoView != null) {  
    12.                     final Bitmap arg2 = Bitmap.createBitmap(bitmap);  
    13.                     ImageCache.getInstance().put(picUrl, arg2);  
    14.                     ViewSinglePhotoActivity.this.runOnUiThread(new Runnable() {  
    15.                         @Override  
    16.                         public void run() {  
    17.                             photoView.setImageBitmap(arg2);  
    18.                         }  
    19.                     });  
    20.                 }  
    21.             }  
    22.   
    23.             @Override  
    24.             protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {  
    25.                 ViewSinglePhotoActivity.this.runOnUiThread(new Runnable() {  
    26.                     @Override  
    27.                     public void run() {  
    28.                         loadPb.setVisibility(View.GONE);  
    29.                         photoView.setImageResource(R.drawable.default_pic);  
    30.                     }  
    31.                 });  
    32.             }  
    33.         });  

    注意事项:

    1.布局中如果使用了fresco的属性,则需要引入命名空间:
    xmlns:fresco="http://schemas.android.com/apk/res-auto"

    2.SimpleDraweeView不支持wrap_content属性,必须给出具体的宽高值,如果width或者height其中有一个值为wrap_content,则可以通过设置宽高比的方法setAspectRatio间接指定其值;

    3.使用SimpleDraweeView后,facebook官方建议不要再使用ImageView的任何属性,如setImageResource、setBackground、setScaleType等;后续版本SimpleDraweeView旨在改为直接继承View;

    4.GenericDraweeHierarchy的属性配置要么在布局中设置完,要么在代码中设置完;simpleDraweeView.getHierarchy()的值一直都不为空,所以不要用这个判断条件来做区分;

    5.关于OOM,1.请给ImageRequest默认配置上setResizeOptions(resizeOptions)属性;对于照片墙等含有大量图片的页面,必须要对图片的大小做限制;网络图片可以通过服务端来对图片的尺寸、质量、图片类型做处理后再返给客户端,但是对于手机本地的图片,就只能通过setResizeOptions来有效降低内存缓存的开销;2.在低内存的情况下或者退出多图页面的情况下,手动释放内存缓存:

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

    6.BaseBitmapDataSubscriber的方法onNewResultImpl中返回的Bitmap会很快被系统回收掉,所以需要再复制一份自行保存;保存时可以采用LruCache方法。

    7.对于webp格式的网络图片内容,如果引入的是fresco:0.6.0;则在安卓4.2.2的手机上没有问题,如果引入的是fresco:0.8.0或者fresco:0.9.0,则在安卓4.2.2的手机上图片会加载失败。

  • 相关阅读:
    break,continue,return的区别
    java中for循环的优化
    Jquery中click函数调用遇到的诡异问题
    MVC中Controller与View的类型绑定问题
    基于8019芯片的在9S12下移植成功的TCP/IP协议族(续)
    MVC中Partialiew使用的一点小总结
    基于8019芯片的在9S12下移植成功的TCP/IP协议族(一)
    9S12单片机的模块驱动程序备忘
    prim算法(zoj1203)
    win7下安装fedora
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/8618772.html
Copyright © 2020-2023  润新知