1.概念介绍

Fresco是Facebook开源Android平台上一个强大的图片加载库,也是迄今为止Android平台上最强大的图片加载库。

优点:相对于其他开源的第三方图片加载库,Fresco拥有更好的内存管理和强大的功能,基本上能满足所有的日常使用场景。

缺点:整体比较大,不过目前的版本已做了拆分,你只需要导入你使用到的功能相关的库。从代码层面来说侵入性太强,体现在要使用它需要用Fresco的组件SimpleDraweeView替换掉Android原生图片显示组件ImageView

2.特性

2.1、内存管理
解压后的图片,即Android中的Bitmap,占用大量的内存。大的内存占用势必引发更加频繁的GC。在5.0以下,GC将会显著地引发界面卡顿。
在5.0以下系统,Fresco将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。

2.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对象。

其流程图如下:

2.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、当图片不再显示在屏幕上时,它会及时地释放内存和空间占用

2.4、Fresco目前所支持的图片格式
a、静态图:png、jpg、web
b、动态图:gif、web格式的gif

3.Fresco的引入及ImagePipeline参数配置

3.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'

3.2 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;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() {@Overridepublic 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() {@Overridepublic 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;}}

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、支持调试时,显示图片加载的Log

 FLog.setMinimumLoggingLevel(FLog.VERBOSE);Set<RequestListener> requestListeners = new HashSet<>();requestListeners.add(new RequestLoggingListener());

d、内存缓存配置完整代码:

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;}@Overridepublic 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;}}}}

e、初始化Fresco

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

4. Fresco图片加载工具封装

package com.facebook.fresco.helper;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;import com.anbetter.log.MLog;
import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.memory.PooledByteBuffer;
import com.facebook.common.memory.PooledByteBufferInputStream;
import com.facebook.common.references.CloseableReference;
import com.facebook.common.util.UriUtil;
import com.facebook.datasource.BaseDataSubscriber;
import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.controller.ControllerListener;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.fresco.helper.blur.BitmapBlurHelper;
import com.facebook.fresco.helper.listener.IDownloadResult;
import com.facebook.fresco.helper.listener.IResult;
import com.facebook.fresco.helper.utils.StreamTool;
import com.facebook.imagepipeline.animated.base.AnimatedImageResult;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.common.RotationOptions;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.image.CloseableAnimatedImage;
import com.facebook.imagepipeline.image.CloseableBitmap;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.image.ImageInfo;
import com.facebook.imagepipeline.request.BasePostprocessor;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;/*** 提供基于Fresco的图片加载工具类* <p>* 在程序入口处添加下面代码,建议在Application的onCreate()方法内添加* Fresco.initialize(this, ImageLoaderConfig.getImagePipelineConfig(this));* <p>**/
public class ImageLoader {public static void loadImage(SimpleDraweeView simpleDraweeView, String url) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, 0, 0, null, null, false);}public static void loadImage(SimpleDraweeView simpleDraweeView, String url, final int reqWidth, final int reqHeight) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, false);}public static void loadImage(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);}public static void loadImage(SimpleDraweeView simpleDraweeView, String url,final int reqWidth, final int reqHeight, BasePostprocessor processor) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);}public static void loadImage(SimpleDraweeView simpleDraweeView, String url, ControllerListener<ImageInfo> controllerListener) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, 0, 0, null, controllerListener, false);}public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, 0, 0, null, null, true);}public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url, final int reqWidth, final int reqHeight) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, true);}public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, 0, 0, processor, null, true);}public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url,final int reqWidth, final int reqHeight, BasePostprocessor processor) {if (TextUtils.isEmpty(url) || simpleDraweeView == null) {return;}Uri uri = Uri.parse(url);loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, true);}public static void loadFile(final SimpleDraweeView simpleDraweeView, String filePath) {if (TextUtils.isEmpty(filePath)) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).path(filePath).build();loadImage(simpleDraweeView, uri, 0, 0, null, null, false);}public static void loadFile(final SimpleDraweeView simpleDraweeView, String filePath, final int reqWidth, final int reqHeight) {if (TextUtils.isEmpty(filePath)) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).path(filePath).build();BaseControllerListener<ImageInfo> controllerListener = new BaseControllerListener<ImageInfo>() {@Overridepublic void onFinalImageSet(String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) {if (imageInfo == null) {return;}ViewGroup.LayoutParams vp = simpleDraweeView.getLayoutParams();vp.width = reqWidth;vp.height = reqHeight;simpleDraweeView.requestLayout();}};loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, controllerListener, false);}public static void loadFile(SimpleDraweeView simpleDraweeView, String filePath, BasePostprocessor processor) {if (TextUtils.isEmpty(filePath)) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).path(filePath).build();loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);}public static void loadFile(SimpleDraweeView simpleDraweeView, String filePath,final int reqWidth, final int reqHeight, BasePostprocessor processor) {if (TextUtils.isEmpty(filePath)) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).path(filePath).build();loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);}public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId) {if (resId == 0 || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).path(String.valueOf(resId)).build();loadImage(simpleDraweeView, uri, 0, 0, null, null, false);}public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId, final int reqWidth, final int reqHeight) {if (resId == 0 || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).path(String.valueOf(resId)).build();loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, false);}public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId, BasePostprocessor processor) {if (resId == 0 || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).path(String.valueOf(resId)).build();loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);}public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId,final int reqWidth, final int reqHeight, BasePostprocessor processor) {if (resId == 0 || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).path(String.valueOf(resId)).build();loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);}public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView, String filename) {if (filename == null || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).path(filename).build();loadImage(simpleDraweeView, uri, 0, 0, null, null, false);}public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView, String filename, final int reqWidth, final int reqHeight) {if (filename == null || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).path(filename).build();loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, false);}public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView, String filename, BasePostprocessor processor) {if (filename == null || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).path(filename).build();loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);}public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView, String filename,final int reqWidth, final int reqHeight, BasePostprocessor processor) {if (filename == null || simpleDraweeView == null) {return;}Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).path(filename).build();loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);}/*** 从网络加载图片,并对图片进行高斯模糊处理** @param view View* @param url  URL*/public static void loadImageBlur(final View view, String url) {loadImage(view.getContext(), url, new IResult<Bitmap>() {@Overridepublic void onResult(Bitmap source) {Bitmap blurBitmap = BitmapBlurHelper.blur(view.getContext(), source);view.setBackground(new BitmapDrawable(view.getContext().getResources(), blurBitmap));}});}public static void loadImageBlur(final View view, String url, final int reqWidth, final int reqHeight) {loadImage(view.getContext(), url, reqWidth, reqHeight, new IResult<Bitmap>() {@Overridepublic void onResult(Bitmap source) {Bitmap blurBitmap = BitmapBlurHelper.blur(view.getContext(), source);view.setBackground(new BitmapDrawable(view.getContext().getResources(), blurBitmap));}});}public static void loadImageBlur(final SimpleDraweeView draweeView, String url) {loadImage(draweeView, url, new BasePostprocessor() {@Overridepublic String getName() {return "blurPostprocessor";}@Overridepublic void process(Bitmap bitmap) {BitmapBlurHelper.blur(bitmap, 35);}});}public static void loadImageBlur(final SimpleDraweeView draweeView, String url, final int reqWidth, final int reqHeight) {loadImage(draweeView, url, reqWidth, reqHeight, new BasePostprocessor() {@Overridepublic String getName() {return "blurPostprocessor";}@Overridepublic void process(Bitmap bitmap) {BitmapBlurHelper.blur(bitmap, 35);}});}public static void loadFileBlur(final SimpleDraweeView draweeView, String filePath) {loadFile(draweeView, filePath, new BasePostprocessor() {@Overridepublic String getName() {return "blurPostprocessor";}@Overridepublic void process(Bitmap bitmap) {BitmapBlurHelper.blur(bitmap, 35);}});}public static void loadFileBlur(final SimpleDraweeView draweeView, String filePath, final int reqWidth, final int reqHeight) {loadFile(draweeView, filePath, reqWidth, reqHeight, new BasePostprocessor() {@Overridepublic String getName() {return "blurPostprocessor";}@Overridepublic void process(Bitmap bitmap) {BitmapBlurHelper.blur(bitmap, 35);}});}public static void loadDrawableBlur(SimpleDraweeView simpleDraweeView, int resId, final int reqWidth, final int reqHeight) {loadDrawable(simpleDraweeView, resId, reqWidth, reqHeight, new BasePostprocessor() {@Overridepublic String getName() {return "blurPostprocessor";}@Overridepublic void process(Bitmap bitmap) {BitmapBlurHelper.blur(bitmap, 35);}});}public static void loadDrawableBlur(SimpleDraweeView simpleDraweeView, int resId) {loadDrawable(simpleDraweeView, resId, new BasePostprocessor() {@Overridepublic String getName() {return "blurPostprocessor";}@Overridepublic void process(Bitmap bitmap) {BitmapBlurHelper.blur(bitmap, 35);}});}public static void loadImage(SimpleDraweeView simpleDraweeView,Uri uri,final int reqWidth,final int reqHeight,BasePostprocessor postprocessor,ControllerListener<ImageInfo> controllerListener,boolean isSmall) {ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(uri);imageRequestBuilder.setRotationOptions(RotationOptions.autoRotate());// 不支持图片渐进式加载,理由:https://github.com/facebook/fresco/issues/1204imageRequestBuilder.setProgressiveRenderingEnabled(false);if (isSmall) {imageRequestBuilder.setCacheChoice(ImageRequest.CacheChoice.SMALL);}if (reqWidth > 0 && reqHeight > 0) {imageRequestBuilder.setResizeOptions(new ResizeOptions(reqWidth, reqHeight));}if (UriUtil.isLocalFileUri(uri)) {imageRequestBuilder.setLocalThumbnailPreviewsEnabled(true);}if (postprocessor != null) {imageRequestBuilder.setPostprocessor(postprocessor);}ImageRequest imageRequest = imageRequestBuilder.build();PipelineDraweeControllerBuilder draweeControllerBuilder = Fresco.newDraweeControllerBuilder();draweeControllerBuilder.setOldController(simpleDraweeView.getController());draweeControllerBuilder.setImageRequest(imageRequest);if (controllerListener != null) {draweeControllerBuilder.setControllerListener(controllerListener);}draweeControllerBuilder.setTapToRetryEnabled(true); // 开启重试功能draweeControllerBuilder.setAutoPlayAnimations(true); // 自动播放gif动画DraweeController draweeController = draweeControllerBuilder.build();simpleDraweeView.setController(draweeController);}/*** 根据提供的图片URL加载原始图(该方法仅针对大小在100k以内的图片,若不确定图片大小,* 请使用下面的downloadImage(String url, final DownloadImageResult loadFileResult) )** @param url             图片URL* @param loadImageResult LoadImageResult*/public static void loadImage(Context context, String url, final IResult<Bitmap> loadImageResult) {loadOriginalImage(context, url, loadImageResult, UiThreadImmediateExecutorService.getInstance());}/*** 根据提供的图片URL加载原始图(该方法仅针对大小在100k以内的图片,若不确定图片大小,* 请使用下面的downloadImage(String url, final DownloadImageResult loadFileResult) )** @param url             图片URL* @param loadImageResult LoadImageResult* @param executor        的取值有以下三个:*                        UiThreadImmediateExecutorService.getInstance() 在回调中进行任何UI操作*                        CallerThreadExecutor.getInstance() 在回调里面做的事情比较少,并且不涉及UI*                        Executors.newSingleThreadExecutor() 你需要做一些比较复杂、耗时的操作,并且不涉及UI(如数据库读写、文件IO),你就不能用上面两个Executor。*                        你需要开启一个后台Executor,可以参考DefaultExecutorSupplier.forBackgroundTasks。*/public static void loadOriginalImage(Context context, String url, final IResult<Bitmap> loadImageResult, Executor executor) {if (TextUtils.isEmpty(url)) {return;}Uri uri = Uri.parse(url);ImagePipeline imagePipeline = Fresco.getImagePipeline();ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);ImageRequest imageRequest = builder.build();// 获取已解码的图片,返回的是BitmapDataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {@Overridepublic void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {if (!dataSource.isFinished()) {return;}CloseableReference<CloseableImage> imageReference = dataSource.getResult();if (imageReference != null) {final CloseableReference<CloseableImage> closeableReference = imageReference.clone();try {CloseableImage closeableImage = closeableReference.get();if (closeableImage instanceof CloseableAnimatedImage) {AnimatedImageResult animatedImageResult = ((CloseableAnimatedImage) closeableImage).getImageResult();if (animatedImageResult != null && animatedImageResult.getImage() != null) {int imageWidth = animatedImageResult.getImage().getWidth();int imageHeight = animatedImageResult.getImage().getHeight();Bitmap.Config bitmapConfig = Bitmap.Config.ARGB_8888;Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, bitmapConfig);animatedImageResult.getImage().getFrame(0).renderFrame(imageWidth, imageHeight, bitmap);if (loadImageResult != null) {loadImageResult.onResult(bitmap);}}} else if (closeableImage instanceof CloseableBitmap) {CloseableBitmap closeableBitmap = (CloseableBitmap) closeableImage;Bitmap bitmap = closeableBitmap.getUnderlyingBitmap();if (bitmap != null && !bitmap.isRecycled()) {// https://github.com/facebook/fresco/issues/648final Bitmap tempBitmap = bitmap.copy(bitmap.getConfig(), false);if (loadImageResult != null) {loadImageResult.onResult(tempBitmap);}}}} finally {imageReference.close();closeableReference.close();}}}@Overridepublic void onFailureImpl(DataSource dataSource) {Throwable throwable = dataSource.getFailureCause();if (throwable != null) {Log.e("ImageLoader", "onFailureImpl = " + throwable.toString());}}}, executor);}/*** 从网络下载图片* 1、根据提供的图片URL,获取图片数据流* 2、将得到的数据流写入指定路径的本地文件** @param url            URL* @param loadFileResult LoadFileResult*/public static void downloadImage(Context context, String url, final IDownloadResult 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>>() {@Overridepublic 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();byte[] data = StreamTool.read(inputStream);StreamTool.write(photoPath, data);loadFileResult.onResult(photoPath);} catch (IOException e) {loadFileResult.onResult(null);e.printStackTrace();} finally {imageReference.close();closeableReference.close();}}}@Overridepublic void onProgressUpdate(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {int progress = (int) (dataSource.getProgress() * 100);if (loadFileResult != null) {loadFileResult.onProgress(progress);}}@Overridepublic void onFailureImpl(DataSource dataSource) {if (loadFileResult != null) {loadFileResult.onResult(null);}Throwable throwable = dataSource.getFailureCause();if (throwable != null) {Log.e("ImageLoader", "onFailureImpl = " + throwable.toString());}}}, Executors.newSingleThreadExecutor());}/*** 从本地文件或网络获取Bitmap** @param context* @param url* @param reqWidth* @param reqHeight* @param loadImageResult*/public static void loadImage(final Context context,String url,final int reqWidth,final int reqHeight,final IResult<Bitmap> loadImageResult) {if (TextUtils.isEmpty(url)) {MLog.i("url is null");return;}Uri uri = Uri.parse(url);if (!UriUtil.isNetworkUri(uri)) {uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).path(url).build();}ImagePipeline imagePipeline = Fresco.getImagePipeline();ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(uri);if (reqWidth > 0 && reqHeight > 0) {imageRequestBuilder.setResizeOptions(new ResizeOptions(reqWidth, reqHeight));}ImageRequest imageRequest = imageRequestBuilder.build();// 获取已解码的图片,返回的是BitmapDataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {@Overridepublic void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {if (!dataSource.isFinished()) {return;}CloseableReference<CloseableImage> imageReference = dataSource.getResult();if (imageReference != null) {final CloseableReference<CloseableImage> closeableReference = imageReference.clone();try {CloseableImage closeableImage = closeableReference.get();if (closeableImage instanceof CloseableAnimatedImage) {AnimatedImageResult animatedImageResult = ((CloseableAnimatedImage) closeableImage).getImageResult();if (animatedImageResult != null && animatedImageResult.getImage() != null) {int imageWidth = animatedImageResult.getImage().getWidth();int imageHeight = animatedImageResult.getImage().getHeight();Bitmap.Config bitmapConfig = Bitmap.Config.ARGB_8888;Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, bitmapConfig);animatedImageResult.getImage().getFrame(0).renderFrame(imageWidth, imageHeight, bitmap);if (loadImageResult != null) {loadImageResult.onResult(bitmap);}}} else if (closeableImage instanceof CloseableBitmap) {CloseableBitmap closeableBitmap = (CloseableBitmap) closeableImage;Bitmap bitmap = closeableBitmap.getUnderlyingBitmap();if (bitmap != null && !bitmap.isRecycled()) {// https://github.com/facebook/fresco/issues/648final Bitmap tempBitmap = bitmap.copy(bitmap.getConfig(), false);if (loadImageResult != null) {loadImageResult.onResult(tempBitmap);}}}} finally {imageReference.close();closeableReference.close();}}}@Overridepublic void onFailureImpl(DataSource dataSource) {Throwable throwable = dataSource.getFailureCause();if (throwable != null) {Log.e("ImageLoader", "onFailureImpl = " + throwable.toString());}}}, UiThreadImmediateExecutorService.getInstance());}/*** 从本地缓存文件中获取Bitmap** @param url* @param loadImageResult*/public static void loadLocalDiskCache(String url, final IResult<Bitmap> loadImageResult) {if (TextUtils.isEmpty(url)) {MLog.i("url is null");return;}ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url)).build();ImagePipeline imagePipeline = Fresco.getImagePipeline();// 获取已解码的图片,返回的是BitmapDataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest,ImageRequest.RequestLevel.DISK_CACHE);dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {@Overridepublic void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {if (!dataSource.isFinished()) {return;}CloseableReference<CloseableImage> imageReference = dataSource.getResult();if (imageReference != null) {final CloseableReference<CloseableImage> closeableReference = imageReference.clone();try {CloseableImage closeableImage = closeableReference.get();if (closeableImage instanceof CloseableAnimatedImage) {AnimatedImageResult animatedImageResult = ((CloseableAnimatedImage) closeableImage).getImageResult();if (animatedImageResult != null && animatedImageResult.getImage() != null) {int imageWidth = animatedImageResult.getImage().getWidth();int imageHeight = animatedImageResult.getImage().getHeight();Bitmap.Config bitmapConfig = Bitmap.Config.ARGB_8888;Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, bitmapConfig);animatedImageResult.getImage().getFrame(0).renderFrame(imageWidth, imageHeight, bitmap);if (loadImageResult != null) {loadImageResult.onResult(bitmap);}}} else if (closeableImage instanceof CloseableBitmap) {CloseableBitmap closeableBitmap = (CloseableBitmap) closeableImage;Bitmap bitmap = closeableBitmap.getUnderlyingBitmap();if (bitmap != null && !bitmap.isRecycled()) {// https://github.com/facebook/fresco/issues/648final Bitmap tempBitmap = bitmap.copy(bitmap.getConfig(), false);if (loadImageResult != null) {loadImageResult.onResult(tempBitmap);}}}} finally {imageReference.close();closeableReference.close();}}}@Overridepublic void onFailureImpl(DataSource dataSource) {Throwable throwable = dataSource.getFailureCause();if (throwable != null) {Log.e("ImageLoader", "onFailureImpl = " + throwable.toString());}}}, UiThreadImmediateExecutorService.getInstance());}}

各种使用场景如下:

4.1 加载网络图片

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

图片布局:

    <com.facebook.drawee.view.SimpleDraweeViewandroid:id="@+id/sdv_1"android:layout_width="90dp"android:layout_height="90dp"app:actualImageScaleType="centerCrop"/>

效果图:

4.2 圆形图片

  <com.facebook.drawee.view.SimpleDraweeViewandroid:id="@+id/sdv_2"android:layout_width="90dp"android:layout_height="90dp"android:layout_marginTop="15dp"app:actualImageScaleType="centerCrop"app:roundAsCircle="true"/>

4.3 圆形带边框的图片

        <com.facebook.drawee.view.SimpleDraweeViewandroid: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"/>

4.4 圆角图片

   <com.facebook.drawee.view.SimpleDraweeViewandroid: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"/>

4.5 设置占位图

<com.facebook.drawee.view.SimpleDraweeViewandroid: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" />

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

 <com.facebook.drawee.view.SimpleDraweeViewandroid:id="@+id/sdv_8"android:layout_width="90dp"android:layout_height="90dp"android:layout_marginTop="15dp"app:actualImageScaleType="centerCrop"app:fadeDuration="3000"/>

4.7 图层叠加显示

 <com.facebook.drawee.view.SimpleDraweeViewandroid:id="@+id/sdv_10"android:layout_width="90dp"android:layout_height="90dp"android:layout_marginTop="15dp"app:actualImageScaleType="centerCrop"app:overlayImage="@mipmap/ic_launcher"/>

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

   <com.facebook.drawee.view.SimpleDraweeViewandroid: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"/>

4.9 从本地文件(比如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>() {@Overridepublic 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);

4.10 从本地资源(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);

4.10 我们知道使用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));

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

   // 需要暂停网络请求时调用public static void pause(){Fresco.getImagePipeline().pause();}// 需要恢复网络请求时调用public static void resume(){Fresco.getImagePipeline().resume();}

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

 /*** 从网络下载图片* 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>>() {@Overridepublic 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();}}}@Overridepublic 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) {@Overridepublic void onResult(String filePath) {}@Overridepublic void onFail() {}});

4.13 不使用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() {@Overridepublic 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;}}});}

Fresco的解析和使用相关推荐

  1. Build.gradule

    apply plugin: 'com.android.application'//说明module的类型,com.android.application为程序,com.android.library为 ...

  2. 【Android 进阶】Android优秀框架

    根据上图我们依次说明: 1,DiskLruCache 硬盘缓存最佳方案(Google提供的一套硬盘缓存的解决方案:DiskLruCache(非Google官方编写,但获得官方认证)) DiskLruC ...

  3. Fresco源码分析之Hierarchy

    上篇文章我们分析了Fresco中的DraweeView,对其中的一些原理以及方法进行了解析.在这过程中我们了解到,DraweeView中是通过DraweeHolder来统一管理的.而DraweeHol ...

  4. Volley 源码解析之图片请求

    一.前言 上篇文章我们分析了网络请求,这篇文章分析对图片的处理操作,如果没看上一篇,可以先看上一篇文章Volley 源码解析之网络请求.Volley 不仅仅对请求网络数据作了良好的封装,还封装了对图片 ...

  5. anroid 图片处理加载对比(image loader,Picasso ,glide,fresco)

    Android 三大图片缓存原理.特性对比 这是我在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事. 从总体设计和原理上对几个图片缓存进行对比,没用到他们 ...

  6. FaceBook推出的Android图片载入库-Fresco

    欢迎关注ndroid-tech-frontier开源项目,定期翻译国外Android优质的技术.开源库.软件架构设计.測试等文章 原文链接:Introducing Fresco: A new imag ...

  7. Android 开源项目android-open-project工具库解析之(一) 依赖注入,图片缓存,网络相关,数据库orm工具包,Android公共库...

    一.依赖注入DI 通过依赖注入降低View.服务.资源简化初始化.事件绑定等反复繁琐工作 AndroidAnnotations(Code Diet) android高速开发框架 项目地址:https: ...

  8. android广告页白屏_年度整理!2056页《大厂安卓岗面试真题解析合集》火爆全网...

    前言 2020年还有最后一个月就结束了,时间一眨眼就过去了.今年面试有没有被面试官虐呢,明年跳槽想跳去哪个大厂呢,这是个问题.说实话,今年我面试也被虐了,为了明年能找到一份心怡的工作,特地的从朋友那里 ...

  9. 【转】Fresco之强大之余的痛楚

    http://www.jianshu.com/p/5364957dcf49 开始之前 如果你有使用的心得,技巧,踩坑经历,希望贡献出来,我会在TODO中慢慢添加(^^)/ 关于Fresco Fresc ...

  10. React Native运行原理解析

    Facebook 于2015年9月15日推出react native for Android 版本, 加上2014年底已经开源的IOS版本,至此RN (react-native)真正成为跨平台的客户端 ...

最新文章

  1. Git CMD - show: Show various types of objects
  2. vorwerk 机器人_福维克(Vorwerk)--吸尘器行业的quot;安利quot;
  3. cgminer linux cpu,Ubuntu Kylin中编译运行cgminer挖矿软件
  4. 【RK PX30】 瑞芯微四核64位工业级芯片PX30 | 安卓核心板
  5. 【javascript】不刷新页面,实时显示当前时间
  6. python关闭exe程序_Win 10 中使用 Python 碰到的奇怪现象
  7. 【Kafka】Kafka 修改某个消费组的偏移量
  8. 常用CNN网络(AlexNet,GoogleNet,VGG,ResNet,DenseNet,inceptionV4)适合初学者
  9. 以Epson 1600k 打印机为例解决使用SC登录虚拟机不能使用问题
  10. ffmpeg使用说明书
  11. 我的梦想是成为一名计算机程序员英语怎么说,我的梦想英语作文带翻译八篇(I have a dream)...
  12. Js中apply和call
  13. 上海市计算机应用基础答案,计算机应用基础10统考(附答案)
  14. 关于微信平台朋友和朋友圈分享不回调的问题。
  15. 重磅:银保监发布消金公司监管评级办法,评级为5级恐被退市(全文重点已标出)
  16. MOS管GS两端并联阻容的作用分析
  17. springboot是如何实现配置文件自动加载的呢
  18. Python就地快速排序
  19. 『Java安全』XStream 1.4-1.4.61.4.10反序列化漏洞CVE-2013-7285复现与浅析
  20. libcurl异步请求+http长连接池

热门文章

  1. android p小米note3,小米note3|RROS-V7.0|安卓9.0|最强大的自定_最新最全的小米Note3ROM刷机包下载、刷机...
  2. SVG Symbols
  3. VSCode选择远程服务器的虚拟环境
  4. 二清资金监管户账务处理实例
  5. html中input type什么意思,HTML中type是什么意思
  6. PMBOK项目管理知识体系包括哪几个知识领域?
  7. linux学习知识体系
  8. python 子域名爆破工具
  9. ubuntu18.04系统无法正常连接网络解决办法
  10. typo:in word ‘ ‘ 问题解决方法