博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android图片加载神器之Fresco,基于各种使用场景的讲解
阅读量:6237 次
发布时间:2019-06-22

本文共 26531 字,大约阅读时间需要 88 分钟。

Fresco是Facebook开源平台上一个强大的图片加载库,也是迄今为止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对象。

其流程图如下:

这里写图片描述

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的使用帮助库,先给大家看看Demo的运行效果图:

常见的各种效果

从网络加载的图片墙

点击图片墙中的照片后,打开的浏览大图界面

一、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' }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

a、在 API < 14 上的机器支持 WebP 时,需要添加以下依赖

compile 'com.facebook.fresco:animated-base-support:0.14.1'
  • 1
  • 1

b、支持GIF动图,需要添加以下依赖

compile 'com.facebook.fresco:animated-gif:0.14.1'
  • 1
  • 1

c、支持WebP,需要添加以下依赖

compile 'com.facebook.fresco:webpsupport:0.14.1'
  • 1
  • 1

d、支持WebP动图,需要添加以下依赖

compile 'com.facebook.fresco:animated-webp:0.14.1'
  • 1
  • 1

e、网络实现层想使用okhttp3,需要添加以下依赖

compile 'com.facebook.fresco:imagepipeline-okhttp3:0.14.1'
  • 1
  • 1

2、ImagePipeline配置

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

File fileCacheDir = context.getApplicationContext().getCacheDir();
  • 1
  • 1

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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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
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; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

d、替换网络实现为okhttp3

OkHttpClient okHttpClient = new OkHttpClient.Builder()                    .addInterceptor(loggingInterceptor)//                    .retryOnConnectionFailure(false)                    .build(); sImagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

e、支持调试时,显示图片加载的Log

FLog.setMinimumLoggingLevel(FLog.VERBOSE);   Set
requestListeners = new HashSet<>(); requestListeners.add(new RequestLoggingListener());
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

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
{ 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; } } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

g、初始化Fresco

Fresco.initialize(context,ImageLoaderConfig.getImagePipelineConfig(context));
  • 1
  • 1

二、Fresco的各种使用场景

从网络加载一张图片

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";ImageLoader.loadImage((SimpleDraweeView)findViewById(R.id.sdv_1), url);
  • 1
  • 2
  • 1
  • 2

1、显示一张图片

  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

效果图如下:

2、显示一张圆形图片

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果图如下:

3、显示一张圆形带边框的图片

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果图如下:

4、显示一张圆角图片

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

效果图如下:

5、显示一张底部是圆角的图片

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

效果图如下:

6、显示一张左上和右下是圆角的图片

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

效果图如下:

7、设置占位图

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

8、带动画的显示(从半透明到不透明)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

9、图层叠加显示

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

10、其它的属性的配置,比如加载进度、加载失败、重试图

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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
() { @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); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

使用:

ImageLoader.loadFile((SimpleDraweeView)itemView, photoInfo.thumbnailUrl, 120, 120);
  • 1
  • 1

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); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用:

ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi);
  • 1
  • 1

效果图如下:

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); } }); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

其内部调用的方法

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); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

使用:

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));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

效果图如下:

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));
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

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);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

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));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

其中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); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

18、从磁盘缓存中移除指定图片的缓存

ImagePipeline imagePipeline = Fresco.getImagePipeline();        Uri uri = Uri.parse(photoInfo.originalUrl); // 下面的操作是异步的 if (imagePipeline.isInDiskCacheSync(uri)) { imagePipeline.evictFromDiskCache(uri); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

19、清空磁盘缓存

Fresco.getImagePipeline().clearDiskCaches();
  • 1
  • 1

20、清空内存缓存

Fresco.getImagePipeline().clearMemoryCaches();
  • 1
  • 1

21、清空缓存(内存缓存 + 磁盘缓存)

Fresco.getImagePipeline().clearCaches();
  • 1
  • 1

22、在列表视图滚动时,不加载图片,等滚动停止后再开始加载图片,提升列表视图的滚动流畅度。

// 需要暂停网络请求时调用    public static void pause(){ Fresco.getImagePipeline().pause(); } // 需要恢复网络请求时调用 public static void resume(){ Fresco.getImagePipeline().resume(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

23、下载图片存储到指定的路径

/**     * 从网络下载图片     * 1、根据提供的图片URL,获取图片数据流     * 2、将得到的数据流写入指定路径的本地文件     *     * @param url            URL     * @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
> dataSource = imagePipeline.fetchEncodedImage(imageRequest, context); dataSource.subscribe(new BaseDataSubscriber
>() { @Override public void onNewResultImpl(DataSource
> dataSource) { if (!dataSource.isFinished() || loadFileResult == null) { return; } CloseableReference
imageReference = dataSource.getResult(); if (imageReference != null) { final CloseableReference
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()); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

使用:

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() { } });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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, null); break; case 2: view.setCompoundDrawables(null, null, drawable, null); break; case 3: view.setCompoundDrawables(null, null, null, drawable); break; } } }); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

三、推荐的使用方法

1、第一种用法

初始化

Phoenix.init(this); // Context
  • 1
  • 1

从网络加载一张图片

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView).load(url);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

从本地加载一张图片

String filePath = "/sdcard/image/test.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView).load(filePath);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

从res下面加载一张图片

SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);Phoenix.with(simpleDraweeView).load(R.drawable.meizi);
  • 1
  • 2
  • 1
  • 2

在写布局文件xml时,我不知道要显示的图片尺寸,需要根据业务逻辑动态的设置要显示的图片的大小,可以像下面这样写:

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .setWidth(100) .setHeight(100) .load(url);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

只知道要显示图片的高或者宽的值,另一个值可以从设置的比例得出

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .setWidth(100) .setAspectRatio(0.6f) // w/h = 6/10 .load(url);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

图片的高斯模糊处理

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .setNeedBlur(true) .load(url);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

加载并显示gif格式的图片

String url = "http://img4.178.com/acg1/201506/227753817857/227754566617.gif";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); Phoenix.with(simpleDraweeView) .load(url);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

加载并显示webp格式的图片

SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);Phoenix.with(simpleDraweeView)        .load(R.drawable.meizi_webp);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

……

2、第二种用法

初始化

Fresco.initialize(context, ImageLoaderConfig.getImagePipelineConfig(context));
  • 1
  • 1

从网络加载一张图片

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

从本地加载一张图片

String filePath = "/sdcard/image/test.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadFile(simpleDraweeView, filePath);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

从res下面加载一张图片

SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi, 100, 100);
  • 1
  • 2
  • 1
  • 2

在写布局文件xml时,我不知道要显示的图片尺寸,需要根据业务逻辑动态的设置要显示的图片的大小,可以像下面这样写:

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url, 120, 120);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

只知道要显示图片的高或者宽的值,另一个值可以从设置的比例得出

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

图片的高斯模糊处理

String url = "http://ww3.sinaimg.cn/large/610dc034jw1f6m4aj83g9j20zk1hcww3.jpg";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImageBlur(simpleDraweeView, url);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

加载并显示gif格式的图片

String url = "http://img4.178.com/acg1/201506/227753817857/227754566617.gif";SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1); ImageLoader.loadImage(simpleDraweeView, url);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

加载并显示webp格式的图片

SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi_webp);
  • 1
  • 2
  • 1
  • 2

……

3、大图浏览器

带动画的效果打开方式,详细细节请查看PhotoWallActivity中的使用

ArrayList
photos = null; PictureBrowse.newBuilder(PhotoWallActivity.this) .setParentView(parent) .setCurrentPosition(position) .setPhotoList(photos) .enabledAnimation(true) .build() .start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

无动画效果的打开方式

ArrayList
photos = null; PictureBrowse.newBuilder(PhotoWallActivity.this) .setParentView(parent) .setCurrentPosition(position) .setPhotoList(photos) .build() .start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我提供了两种图片加载使用方式,你想使用那种图片加载方式,全看个人爱好(推荐使用第一种方式)。

代码我已上传到github上了,地址:

你可能感兴趣的文章
「译」Android ViewPropertyAnimator 介绍(3.1的动画机制)
查看>>
Android 程序员学习 iOS ——故事从这里开始
查看>>
【译】Ngnix实现一个缓存和缩略处理的反向代理服务器
查看>>
WebGL实现HTML5贪吃蛇3D游戏
查看>>
webstorm配置eslint注意
查看>>
PHP加密与实际应用
查看>>
ikun 潜入?疑似 B 站后台源码泄露
查看>>
通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise
查看>>
斯坦福iOS_系列视频之俄罗斯方块
查看>>
JavaScript数据类型的一些注意要点
查看>>
结合P2P软件使用Ansible分发大文件
查看>>
特斯拉Model 3成为核心产品 生产线问题刚好又坏在运输环节 ...
查看>>
如何在Windows系统下的Eclipse中安装Cloud Toolkit
查看>>
阿里云服务器实例规格族配置怎么选?
查看>>
关于K8s集群器日志收集的总结
查看>>
Java中String和StringBuffer对于拼接运算中效率的对比 ...
查看>>
吉利自动驾驶之路将完成:到2022年推出L5级别亚运园区接驳车 ...
查看>>
阿里重磅开源首款自研科学计算引擎Mars,揭秘超大规模科学计算 ...
查看>>
java B2B2C 源码 多级分销Springcloud多租户电子商城系统-使用spring cloud Bus刷新配置...
查看>>
Ionic如何创建自定义展开标题组件
查看>>