Android图片加载神器之Fresco,基于各种使用场景的讲解

采得百花成蜜后,为谁辛苦为谁甜。这篇文章主要讲述Android图片加载神器之Fresco,基于各种使用场景的讲解相关的知识,希望能为你提供帮助。
转载请标明出处: http://blog.csdn.net/android_ls/article/details/53137867
Fresco是Facebook开源android平台上一个强大的图片加载库, 也是迄今为止Android平台上最强大的图片加载库。
优点: 相对于其他开源的第三方图片加载库, Fresco拥有更好的内存管理和强大的功能, 基本上能满足所有的日常使用场景。
缺点: 整体比较大, 不过目前的版本已做了拆分, 你只需要导入你使用到的功能相关的库。从代码层面来说侵入性太强, 体现在要使用它需要用Fresco的组件SimpleDraweeView替换掉Android原生图片显示组件ImageView, 这也是很多人不愿意在项目中接入Fresco的主要原因。
特性:
1、内存管理
解压后的图片, 即Android中的Bitmap, 占用大量的内存。大的内存占用势必引发更加频繁的GC。在5.0以下, GC将会显著地引发界面卡顿。
在5.0以下系统, Fresco将图片放到一个特别的内存区域。当然, 在图片不显示的时候, 占用的内存会自动被释放。这会使得APP更加流畅, 减少因图片内存占用而引发的OOM。
2、Image Pipeline
Fresco中设计有一个叫做 Image Pipeline 的模块。它负责从网络, 从本地文件系统, 本地资源加载图片和管理。为了最大限度节省空间和CPU时间, 它含有3级缓存设计( 2级内存, 1级磁盘) 。两个内存缓存为Bitmap缓存和未解码的图片缓存, 这样既可以加快图片的加载速度, 又能节省内存的占用( 解码后的图片就是Bitmap, 其占用内存相对未解码的图片数据而言会大很多) 。
Image pipeline 负责完成加载图像, 变成Android设备可呈现的形式所要经历的大致流程如下:
a、根据Uri在已解码的( Bitmap缓存) 内存缓存中查找, 找到了则返回Bitmap对象; 如果没找到, 则开启后台线程开始后续的工作。
b、根据Uri在未解码的内存缓存中查找, 若找到了则解码, 然后缓存到已解码的内存缓存中, 并且返回Bitmap对象。
d、如果在未解码的内存缓存中没找到, 则根据Uri在磁盘缓存中查找, 若找到了则读取数据( byte数组) , 并缓存到未解码的内存缓存中, 解码、然后缓存到已解码的内存缓存中, 并且返回Bitmap对象。
e、如果在磁盘缓存中没找到, 则从网络或者本地加载数据。加载完成后, 依次缓存到磁盘缓存、未解码的内存缓存中。解码、然后缓存到已解码的内存缓存中, 并且返回Bitmap对象。
其流程图如下:

Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

3、Drawees
Fresco 中设计有一个叫做 Drawees 模块, 负责图片的呈现。它由三个元素组成分别是:
DraweeView 继承于 View, 负责图片的显示。
DraweeHierarchy 用于组织和维护最终绘制和呈现的 Drawable 对象。
DraweeController 负责和ImagePipeline的交互, 可以创建一个这个类的实例, 来实现对所要显示的图片做更多的控制。
一般情况下, 使用 SimpleDraweeView 即可, 你可以配置其XML属性来实现各式各样的展示效果。
a、在图片加载完成前显示占位图;
b、在图片加载的过程中显示加载进度图;
c、加载成功后, 将占位图或者加载进度图, 自动替换为目标图片。
d、加载失败后, 它会显示加载失败的图( 若没配置加载失败的图, 则显示的是占位图)
e、加载失败后, 若配置过重试图, 则会显示重试图, 用户点击可以重新去加载图片( 默认配置可重试3次)
f、自定义居中焦点( 配合Google提供的服务可以实现人脸识别, 经测试国内目前使用不了)
g、显示圆角图、圆形图和圆圈;
h、添加覆盖物( 图层叠加) ;
j、 实现图片的按下效果;
k、图片的渐进式呈现; ( 目前只支持Jpeg格式的图片)
x、当图片不再显示在屏幕上时, 它会及时地释放内存和空间占用。
4、Fresco目前所支持的图片格式
a、静态图: png、jpg、web
b、动态图: gif、web格式的gif
以上聊了这么多, 大概意思就是Fresco出身名门, 很好很强大, 超牛逼! 接下来我们来聊聊在项目中的具体使用。我专门写了一个针对Fresco的使用帮助库( github地址: https://github.com/hpdx/fresco-helper) , 先给大家看看Demo的运行效果图:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

常见的各种效果
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

从网络加载的图片墙
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

点击图片墙中的照片后, 打开的浏览大图界面
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

一、Fresco的引入及ImagePipeline参数配置
1、在build.gradle文件中添加依赖
dependencies { // ......compile ' com.facebook.fresco:fresco:0.14.1' compile ' com.facebook.fresco:animated-base-support:0.14.1' compile ' com.facebook.fresco:animated-gif:0.14.1' compile ' com.facebook.fresco:webpsupport:0.14.1' compile ' com.facebook.fresco:animated-webp:0.14.1' compile ' com.facebook.fresco:imagepipeline-okhttp3:0.14.1' }

a、在 API < 14 上的机器支持 WebP 时, 需要添加以下依赖
compile ' com.facebook.fresco:animated-base-support:0.14.1'

b、支持GIF动图, 需要添加以下依赖
compile ' com.facebook.fresco:animated-gif:0.14.1'

c、支持WebP, 需要添加以下依赖
compile ' com.facebook.fresco:webpsupport:0.14.1'

d、支持WebP动图, 需要添加以下依赖
compile ' com.facebook.fresco:animated-webp:0.14.1'

e、网络实现层想使用okhttp3, 需要添加以下依赖
compile ' com.facebook.fresco:imagepipeline-okhttp3:0.14.1'

2、ImagePipeline配置
a、磁盘缓存目录, 推荐缓存到应用本身的缓存文件夹, 这么做的好处是: 当应用被用户卸载后能自动清除缓存, 增加用户好感( 可能以后用得着时, 还会想起我) ; 一些内存清理软件可以扫描出来, 进行内存的清理。
File fileCacheDir = context.getApplicationContext().getCacheDir();

b、配置磁盘缓存, 大部分的应用有一个磁盘缓存就够了, 但是在一些情况下, 你可能需要两个缓存。比如你想把小文件放在一个缓存中( 50*50及以下尺寸) , 大文件放在另外一个文件中, 这样小文件就不会因大文件的频繁变动而被从缓存中移除。
DiskCacheConfig mainDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR) .setBaseDirectoryPath(fileCacheDir) .build(); DiskCacheConfig smallDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryPath(fileCacheDir) .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR) .setMaxCacheSize(MAX_DISK_SMALL_CACHE_SIZE) .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_SMALL_ONLOWDISKSPACE_CACHE_SIZE) .build();

c、ImagePipeline的完整配置代码如下:
package com.facebook.fresco.helper.config; import android.app.ActivityManager; import android.content.Context; import android.graphics.Bitmap; import com.facebook.cache.disk.DiskCacheConfig; import com.facebook.common.logging.FLog; import com.facebook.common.memory.MemoryTrimType; import com.facebook.common.memory.MemoryTrimmable; import com.facebook.common.memory.MemoryTrimmableRegistry; import com.facebook.common.memory.NoOpMemoryTrimmableRegistry; import com.facebook.common.util.ByteConstants; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.fresco.helper.utils.MLog; import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.facebook.imagepipeline.decoder.ProgressiveJpegConfig; import com.facebook.imagepipeline.image.ImmutableQualityInfo; import com.facebook.imagepipeline.image.QualityInfo; import com.facebook.imagepipeline.listener.RequestListener; import com.facebook.imagepipeline.listener.RequestLoggingListener; import java.io.File; import java.util.HashSet; import java.util.Set; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; /** * * Created by android_ls on 16/9/8. */ public class ImageLoaderConfig {private static final String IMAGE_PIPELINE_CACHE_DIR = " image_cache" ; private static final String IMAGE_PIPELINE_SMALL_CACHE_DIR = " image_small_cache" ; private static final int MAX_DISK_SMALL_CACHE_SIZE = 10 * ByteConstants.MB; private static final int MAX_DISK_SMALL_ONLOWDISKSPACE_CACHE_SIZE = 5 * ByteConstants.MB; private static ImagePipelineConfig sImagePipelineConfig; /** * Creates config using android http stack as network backend. */ public static ImagePipelineConfig getImagePipelineConfig(final Context context) { if (sImagePipelineConfig = = null) { /** * 推荐缓存到应用本身的缓存文件夹, 这么做的好处是: * 1、当应用被用户卸载后能自动清除缓存, 增加用户好感( 可能以后用得着时, 还会想起我) * 2、一些内存清理软件可以扫描出来, 进行内存的清理 */ File fileCacheDir = context.getApplicationContext().getCacheDir(); //if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //fileCacheDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + " /Fresco" ); //}DiskCacheConfig mainDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR) .setBaseDirectoryPath(fileCacheDir) .build(); DiskCacheConfig smallDiskCacheConfig = DiskCacheConfig.newBuilder(context) .setBaseDirectoryPath(fileCacheDir) .setBaseDirectoryName(IMAGE_PIPELINE_SMALL_CACHE_DIR) .setMaxCacheSize(MAX_DISK_SMALL_CACHE_SIZE) .setMaxCacheSizeOnLowDiskSpace(MAX_DISK_SMALL_ONLOWDISKSPACE_CACHE_SIZE) .build(); FLog.setMinimumLoggingLevel(FLog.VERBOSE); Set< RequestListener> requestListeners = new HashSet< > (); requestListeners.add(new RequestLoggingListener()); // 当内存紧张时采取的措施 MemoryTrimmableRegistry memoryTrimmableRegistry = NoOpMemoryTrimmableRegistry.getInstance(); memoryTrimmableRegistry.registerMemoryTrimmable(new MemoryTrimmable() { @ Override public void trim(MemoryTrimType trimType) { final double suggestedTrimRatio = trimType.getSuggestedTrimRatio(); MLog.i(String.format(" Fresco onCreate suggestedTrimRatio : %d" , suggestedTrimRatio)); if (MemoryTrimType.OnCloseToDalvikHeapLimit.getSuggestedTrimRatio() = = suggestedTrimRatio || MemoryTrimType.OnSystemLowMemoryWhileAppInBackground.getSuggestedTrimRatio() = = suggestedTrimRatio || MemoryTrimType.OnSystemLowMemoryWhileAppInForeground.getSuggestedTrimRatio() = = suggestedTrimRatio ) { // 清除内存缓存 Fresco.getImagePipeline().clearMemoryCaches(); } } }); HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) //.retryOnConnectionFailure(false) .build(); sImagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient) //sImagePipelineConfig = ImagePipelineConfig.newBuilder(context) .setBitmapsConfig(Bitmap.Config.RGB_565) // 若不是要求忒高清显示应用, 就用使用RGB_565吧( 默认是ARGB_8888) .setDownsampleEnabled(true) // 在解码时改变图片的大小, 支持PNG、JPG以及WEBP格式的图片, 与ResizeOptions配合使用 // 设置Jpeg格式的图片支持渐进式显示 .setProgressiveJpegConfig(new ProgressiveJpegConfig() { @ Override public int getNextScanNumberToDecode(int scanNumber) { return scanNumber + 2; }public QualityInfo getQualityInfo(int scanNumber) { boolean isGoodEnough = (scanNumber > = 5); return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false); } }) .setRequestListeners(requestListeners) .setMemoryTrimmableRegistry(memoryTrimmableRegistry) // 报内存警告时的监听 // 设置内存配置 .setBitmapMemoryCacheParamsSupplier(new BitmapMemoryCacheParamsSupplier( (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))) .setMainDiskCacheConfig(mainDiskCacheConfig) // 设置主磁盘配置 .setSmallImageDiskCacheConfig(smallDiskCacheConfig) // 设置小图的磁盘配置 .build(); } return sImagePipelineConfig; }}

d、替换网络实现为okhttp3
OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) //.retryOnConnectionFailure(false) .build(); sImagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient)

e、支持调试时, 显示图片加载的Log
FLog.setMinimumLoggingLevel(FLog.VERBOSE); Set< RequestListener> requestListeners = new HashSet< > (); requestListeners.add(new RequestLoggingListener());

f、内存缓存配置完整代码:
package com.facebook.fresco.helper.config; import android.app.ActivityManager; import android.os.Build; import com.facebook.common.internal.Supplier; import com.facebook.common.util.ByteConstants; import com.facebook.fresco.helper.utils.MLog; import com.facebook.imagepipeline.cache.MemoryCacheParams; /** * 内存缓存配置 * https://github.com/facebook/fresco/issues/738 * * Created by android_ls on 16/9/8. */ public class BitmapMemoryCacheParamsSupplier implements Supplier< MemoryCacheParams> {private final ActivityManager mActivityManager; public BitmapMemoryCacheParamsSupplier(ActivityManager activityManager) { mActivityManager = activityManager; }@ Override public MemoryCacheParams get() { if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.LOLLIPOP) { return new MemoryCacheParams(getMaxCacheSize(), // 内存缓存中总图片的最大大小,以字节为单位。 56,// 内存缓存中图片的最大数量。 Integer.MAX_VALUE,// 内存缓存中准备清除但尚未被删除的总图片的最大大小,以字节为单位。 Integer.MAX_VALUE,// 内存缓存中准备清除的总图片的最大数量。 Integer.MAX_VALUE); // 内存缓存中单个图片的最大大小。 } else { return new MemoryCacheParams( getMaxCacheSize(), 256, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); } }private int getMaxCacheSize() { final int maxMemory = Math.min(mActivityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE); MLog.i(String.format(" Fresco Max memory [%d] MB" , (maxMemory/ByteConstants.MB))); if (maxMemory < 32 * ByteConstants.MB) { return 4 * ByteConstants.MB; } else if (maxMemory < 64 * ByteConstants.MB) { return 6 * ByteConstants.MB; } else { // We don' t want to use more ashmem on Gingerbread for now, since it doesn' t respond well to // native memory pressure (doesn' t throw exceptions, crashes app, crashes phone) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { return 8 * ByteConstants.MB; } else { return maxMemory / 4; } } }}

g、初始化Fresco
Fresco.initialize(context,ImageLoaderConfig.getImagePipelineConfig(context));

二、Fresco的各种使用场景
从网络加载一张图片
String url = " http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg" ; ImageLoader.loadImage((SimpleDraweeView)findViewById(R.id.sdv_1), url);

1、显示一张图片
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_1" android:layout_width= " 90dp" android:layout_height= " 90dp" app:actualImageScaleType= " centerCrop" />

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

2、显示一张圆形图片
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_2" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:roundAsCircle= " true" />

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

3、显示一张圆形带边框的图片
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_3" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:roundAsCircle= " true" app:roundingBorderColor= " #fff3cf44" app:roundingBorderWidth= " 2dp" />

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

4、显示一张圆角图片
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_4" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:roundAsCircle= " false" app:roundedCornerRadius= " 10dp" />

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

5、显示一张底部是圆角的图片
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_5" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:roundAsCircle= " false" app:roundedCornerRadius= " 10dp" app:roundTopLeft= " false" app:roundTopRight= " false" app:roundBottomLeft= " true" app:roundBottomRight= " true" />

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

6、显示一张左上和右下是圆角的图片
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_6" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:roundAsCircle= " false" app:roundedCornerRadius= " 10dp" app:roundTopLeft= " true" app:roundTopRight= " false" app:roundBottomLeft= " false" app:roundBottomRight= " true" />

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

7、设置占位图
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_7" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:placeholderImage= " @ mipmap/ic_launcher" app:placeholderImageScaleType= " centerCrop" />

8、带动画的显示( 从半透明到不透明)
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_8" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:fadeDuration= " 3000" />

9、图层叠加显示
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_10" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:overlayImage= " @ mipmap/ic_launcher" />

10、其它的属性的配置, 比如加载进度、加载失败、重试图
< com.facebook.drawee.view.SimpleDraweeView android:id= " @ + id/sdv_11" android:layout_width= " 90dp" android:layout_height= " 90dp" android:layout_marginTop= " 15dp" app:actualImageScaleType= " centerCrop" app:failureImage= " @ mipmap/ic_launcher" app:failureImageScaleType= " centerInside" app:retryImage= " @ mipmap/ic_launcher" app:retryImageScaleType= " centerCrop" app:progressBarImage= " @ mipmap/ic_launcher" app:progressBarImageScaleType= " centerCrop" app:progressBarAutoRotateInterval= " 5000" />

11、从本地文件( 比如SDCard上) 加载图片
public static void loadFile(final SimpleDraweeView draweeView, String filePath, final int reqWidth, final int reqHeight) { Uri uri = new Uri.Builder() .scheme(UriUtil.LOCAL_FILE_SCHEME) .path(filePath) .build(); ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setRotationOptions(RotationOptions.autoRotate()) .setLocalThumbnailPreviewsEnabled(true) .setResizeOptions(new ResizeOptions(reqWidth, reqHeight)) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(draweeView.getController()) .setControllerListener(new BaseControllerListener< ImageInfo> () { @ Override public void onFinalImageSet(String id, @ Nullable ImageInfo imageInfo, @ Nullable Animatable anim) { if (imageInfo = = null) { return; }ViewGroup.LayoutParams vp = draweeView.getLayoutParams(); vp.width = reqWidth; vp.height = reqHeight; draweeView.requestLayout(); } }) .build(); draweeView.setController(controller); }

使用:
ImageLoader.loadFile((SimpleDraweeView)itemView, photoInfo.thumbnailUrl, 120, 120);

12、从本地资源( Resources) 加载图片
public static void loadDrawable(SimpleDraweeView draweeView, int resId) { Uri uri = new Uri.Builder() .scheme(UriUtil.LOCAL_RESOURCE_SCHEME) .path(String.valueOf(resId)) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(uri) .setOldController(draweeView.getController()) .build(); draweeView.setController(controller); }

使用:
ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi);

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

13、对图片进行性高斯模糊处理
public static void loadImageBlur(final SimpleDraweeView draweeView, String url) { loadImage(draweeView, url, new BasePostprocessor() { @ Override public String getName() { return " blurPostprocessor" ; }@ Override public void process(Bitmap bitmap) { BitmapBlurHelper.blur(bitmap, 35); } }); }

其内部调用的方法
public static void loadImage(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) { if (TextUtils.isEmpty(url)) { return; }Uri uri = Uri.parse(url); ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setRotationOptions(RotationOptions.autoRotate()) .setPostprocessor(processor) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(simpleDraweeView.getController()) .build(); simpleDraweeView.setController(controller); }

使用:
String url = " http://a.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d3de795ad0628535e4dd6fe2.jpg" ; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); simpleDraweeView.setAspectRatio(0.7f); ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams(); lvp.width = DensityUtil.getDisplayWidth(this); ImageLoader.loadImageBlur(simpleDraweeView, url, DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this));

效果图如下:
Android图片加载神器之Fresco,基于各种使用场景的讲解

文章图片

14、我们知道使用Fresco加载并显示一张图片, 需要指定SimpleDraweeView的宽高或者指定其中一个值并设置宽高比, 可是我真的不知道要显示的图片有多大, 该显示多大? 可以帮我搞定吗? 答案是肯定的。
String url = " http://feed.chujianapp.com/20161108/452ab5752287a99a1b5387e2cd849006.jpg@ 1080w" ; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url, new SingleImageControllerListener(simpleDraweeView));

15、从网络加载并显示gif格式的图片
String url = " http://img4.178.com/acg1/201506/227753817857/227754566617.gif" ; SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url);

16、加载并显示webp格式的图片
SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams(); lvp.width = DensityUtil.getDisplayWidth(this); simpleDraweeView.setAspectRatio(0.6f); // 设置宽高比ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi_webp, DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this));

其中R.drawable.meizi_webp为meizi_webp.webp
17、从内存缓存中移除指定图片的缓存
if (!TextUtils.isEmpty(photoInfo.originalUrl)) { ImagePipeline imagePipeline = Fresco.getImagePipeline(); Uri uri = Uri.parse(photoInfo.originalUrl); if (imagePipeline.isInBitmapMemoryCache(uri)) { imagePipeline.evictFromMemoryCache(uri); } }

18、从磁盘缓存中移除指定图片的缓存
ImagePipeline imagePipeline = Fresco.getImagePipeline(); Uri uri = Uri.parse(photoInfo.originalUrl); // 下面的操作是异步的 if (imagePipeline.isInDiskCacheSync(uri)) { imagePipeline.evictFromDiskCache(uri); }

19、清空磁盘缓存
Fresco.getImagePipeline().clearDiskCaches();

20、清空内存缓存
Fresco.getImagePipeline().clearMemoryCaches();

21、清空缓存( 内存缓存 + 磁盘缓存)
Fresco.getImagePipeline().clearCaches();

22、在列表视图滚动时, 不加载图片, 等滚动停止后再开始加载图片, 提升列表视图的滚动流畅度。
// 需要暂停网络请求时调用 public static void pause(){ Fresco.getImagePipeline().pause(); }// 需要恢复网络请求时调用 public static void resume(){ Fresco.getImagePipeline().resume(); }

23、下载图片存储到指定的路径
/** * 从网络下载图片 * 1、根据提供的图片URL, 获取图片数据流 * 2、将得到的数据流写入指定路径的本地文件 * * @ param urlURL * @ param loadFileResult LoadFileResult */ public static void downloadImage(Context context, String url, final DownloadImageResult loadFileResult) { if (TextUtils.isEmpty(url)) { return; }Uri uri = Uri.parse(url); ImagePipeline imagePipeline = Fresco.getImagePipeline(); ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri); ImageRequest imageRequest = builder.build(); // 获取未解码的图片数据 DataSource< CloseableReference< PooledByteBuffer> > dataSource = imagePipeline.fetchEncodedImage(imageRequest, context); dataSource.subscribe(new BaseDataSubscriber< CloseableReference< PooledByteBuffer> > () { @ Override public void onNewResultImpl(DataSource< CloseableReference< PooledByteBuffer> > dataSource) { if (!dataSource.isFinished() || loadFileResult = = null) { return; }CloseableReference< PooledByteBuffer> imageReference = dataSource.getResult(); if (imageReference != null) { final CloseableReference< PooledByteBuffer> closeableReference = imageReference.clone(); try { PooledByteBuffer pooledByteBuffer = closeableReference.get(); InputStream inputStream = new PooledByteBufferInputStream(pooledByteBuffer); String photoPath = loadFileResult.getFilePath(); Log.i(" ImageLoader" , " photoPath = " + photoPath); byte[] data = StreamTool.read(inputStream); StreamTool.write(photoPath, data); loadFileResult.onResult(photoPath); } catch (IOException e) { loadFileResult.onFail(); e.printStackTrace(); } finally { imageReference.close(); closeableReference.close(); } } }@ Override public void onFailureImpl(DataSource dataSource) { if (loadFileResult != null) { loadFileResult.onFail(); }Throwable throwable = dataSource.getFailureCause(); if (throwable != null) { Log.e(" ImageLoader" , " onFailureImpl = " + throwable.toString()); } } }, Executors.newSingleThreadExecutor()); }

使用:
String url = " http://feed.chujianapp.com/20161108/452ab5752287a99a1b5387e2cd849006.jpg@ 1080w" ; String filePath = " " ; ImageLoader.downloadImage(context, url, new DownloadImageResult(filePath) {@ Override public void onResult(String filePath) {}@ Override public void onFail() {} });

【Android图片加载神器之Fresco,基于各种使用场景的讲解】24、不使用SimpleDraweeView组件, 但是想使用Fresco去加载图片( 两级内存缓存+ 磁盘缓存要有) 并显示到其他组件上( 比如显示在TextView的drawableLeft属性上或者显示为View的背景) 。
public static void loadTextDrawable(final TextView view, String url, final int direction, final int iconWidth, final int iconHeight) { ImageLoader.loadImage(view.getContext(), url, new LoadImageResult() { @ Override public void onResult(Bitmap bitmap) { Drawable drawable = new BitmapDrawable(view.getContext().getResources(), bitmap); final int width = DensityUtil.dipToPixels(view.getContext(), iconWidth); final int height = DensityUtil.dipToPixels(view.getContext(), iconHeight); drawable.setBounds(0, 0, width, height); switch (direction) { case 0: view.setCompoundDrawables(drawable, null, null, null); break; case 1: view.setCompoundDrawables(null, drawable, null,

    推荐阅读