您的位置:首页 > 移动开发 > Android开发

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

2018-03-23 14:53 656 查看
转载出处: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对象。其流程图如下: 


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的运行效果图: 


常见的各种效果 


从网络加载的图片墙 


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


一、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<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;
}

}
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<RequestListener> 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<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;
}
}
}

}
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、显示一张图片
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/sdv_1"
android:layout_width="90dp"
android:layout_height="90dp"
app:actualImageScaleType="centerCrop"/>
1
2
3
4
5
1
2
3
4
5
效果图如下: 


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"/>
1
2
3
4
5
6
7
1
2
3
4
5
6
7
效果图如下: 


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"/>
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
效果图如下: 


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"/>
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
效果图如下: 


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"/>
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、显示一张左上和右下是圆角的图片
<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"/>
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、设置占位图
<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" />
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
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"/>
1
2
3
4
5
6
7
1
2
3
4
5
6
7
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"/>
1
2
3
4
5
6
7
1
2
3
4
5
6
7
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"/>
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<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);
}
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.webp17、从内存缓存中移除指定图片的缓存
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<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());
}
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<PhotoInfo> 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<PhotoInfo> 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
我提供了两种图片加载使用方式,你想使用那种图片加载方式,全看个人爱好(推荐使用第一种方式)。文中的照片墙实现:https://github.com/hpdx/fresco-photoview (原来是包含在fresco-helper中的,后来做了拆分)代码我已上传到github上了,地址:https://github.com/hpdx/fresco-helper
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐