码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2016-11-12 20:17:45      阅读:423      评论:0      收藏:0      [点我收藏+]

标签:缺点   util   als   模糊   维护   sync   eof   end   aspect   

转载请标明出处: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、检查内存缓存,如有,返回
b、后台线程开始后续工作
c、检查是否在未解码内存缓存中。如有,解码,变换,返回,然后缓存到内存缓存中。
d、检查是否在磁盘缓存中,如果有,变换,返回。缓存到未解码缓存和内存缓存中。
e、从网络或者本地加载。加载完成后,解码,变换,返回。存到各个缓存中。

其流程图如下:
技术分享

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的引入及初始化
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‘
}

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

compile ‘com.facebook.fresco:animated-base-support:0.14.1‘

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

 compile ‘com.facebook.fresco:animated-gif:0.14.1‘

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

compile ‘com.facebook.fresco:webpsupport:0.14.1‘

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

 compile ‘com.facebook.fresco:animated-webp:0.14.1‘

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

compile ‘com.facebook.fresco:imagepipeline-okhttp3:0.14.1‘

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

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

配置磁盘缓存,大部分的应用有一个磁盘缓存就够了,但是在一些情况下,你可能需要两个缓存。比如你想把小文件放在一个缓存中(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();

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

}

替换网络实现为okhttp3

       OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(loggingInterceptor)
//                    .retryOnConnectionFailure(false)
                    .build();

            sImagePipelineConfig = OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient)

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

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

初始化Fresco

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

二、Fresco使用的各个场景

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

从网络加载并显示一张图片

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

效果图如下:
技术分享

从网络加载并显示一张圆形图片

  <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"/>

效果图如下:
技术分享

从网络加载并显示一张圆形带边框的图片

        <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"/>

效果图如下:
技术分享

从网络加载并显示一张圆角图片

   <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"/>

效果图如下:
技术分享

   <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"/>

效果图如下:
技术分享

     <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"/>

效果图如下:
技术分享

设置占位图

<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" />

带动画的渐进式显示

 <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"/>

图层叠加显示

 <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"/>

其他的属性,比如加载进度、加载失败、重试图

   <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"/>

从本地文件(比如SDCard上)加载图片

  public static void loadFile(final SimpleDraweeView draweeView, String filePath, final int reqWidth, final int reqHeight) {
        Uri uri = new Uri.Builder()
                .scheme(UriUtil.LOCAL_FILE_SCHEME)
                .path(filePath)
                .build();
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setRotationOptions(RotationOptions.autoRotate())
                .setLocalThumbnailPreviewsEnabled(true)
                .setResizeOptions(new ResizeOptions(reqWidth, reqHeight))
                .build();
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setOldController(draweeView.getController())
                .setControllerListener(new BaseControllerListener<ImageInfo>() {
                    @Override
                    public void onFinalImageSet(String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) {
                        if (imageInfo == null) {
                            return;
                        }

                        ViewGroup.LayoutParams vp = draweeView.getLayoutParams();
                        vp.width = reqWidth;
                        vp.height = reqHeight;
                        draweeView.requestLayout();
                    }
                })
                .build();
        draweeView.setController(controller);
    }

使用:

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

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

效果图如下:
技术分享

对图片进行性高斯模糊处理

public static void loadImageBlur(final SimpleDraweeView draweeView, String url) {
        loadImage(draweeView, url, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(Bitmap bitmap) {
                BitmapBlurHelper.blur(bitmap, 35);
            }
        });
    }

其内部调用的方法

public static void loadImage(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) {
        if (TextUtils.isEmpty(url)) {
            return;
        }

        Uri uri = Uri.parse(url);
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setRotationOptions(RotationOptions.autoRotate())
                .setPostprocessor(processor)
                .build();
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setOldController(simpleDraweeView.getController())
                .build();
        simpleDraweeView.setController(controller);
    }

使用:

String url = "http://a.hiphotos.baidu.com/image/pic/item/55e736d12f2eb938d3de795ad0628535e4dd6fe2.jpg";

  SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);

  simpleDraweeView.setAspectRatio(0.7f);

  ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams();
  lvp.width = DensityUtil.getDisplayWidth(this);

  ImageLoader.loadImageBlur(simpleDraweeView, url,
                DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this));

效果图如下:
技术分享

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

从网络加载并显示gif格式的图片

   String url = "http://img4.178.com/acg1/201506/227753817857/227754566617.gif";

        SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);
        ImageLoader.loadImage(simpleDraweeView, url);

加载并显示webp格式的图片

 SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);
        ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams();
        lvp.width = DensityUtil.getDisplayWidth(this);
        simpleDraweeView.setAspectRatio(0.6f); // 设置宽高比

        ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi_webp,
                DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this));

其中R.drawable.meizi_webp为meizi_webp.webp

从内存缓存中移除指定图片的缓存

if (!TextUtils.isEmpty(photoInfo.originalUrl)) {
                ImagePipeline imagePipeline = Fresco.getImagePipeline();
                Uri uri = Uri.parse(photoInfo.originalUrl);
                if (imagePipeline.isInBitmapMemoryCache(uri)) {
                    imagePipeline.evictFromMemoryCache(uri);
                }
            }

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

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

清空磁盘缓存

 Fresco.getImagePipeline().clearDiskCaches();

清空内存缓存

Fresco.getImagePipeline().clearMemoryCaches();

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

Fresco.getImagePipeline().clearCaches();

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

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

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

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

  /**
     * 从网络下载图片
     * 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());
    }

使用:

 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() {

        }
    });

不使用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;
                }
            }
        });
    }

谢谢,听我唠叨这么久。

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

标签:缺点   util   als   模糊   维护   sync   eof   end   aspect   

原文地址:http://blog.csdn.net/android_ls/article/details/53137867

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!