图片加载框架之Fresco的使用介绍

目录(?)[+]

1:简介

Fresco是Facebook最新推出的一款用于Android应用中展示图片的强大图片库,可以从网络、本地存储和本地资源中加载图片。相对于ImageLoader,拥有更快的图片下载速度以及可以加载和显示gif图等诸多优势,是个很好的图片框架。

2:特点

2.1:内存管理

在5.0以下系统,Fresco将图片放到一个特别的内存区域。当然,在图片不显示的时候,占用的内存会自动被释放。这会使得APP更加流畅,减少因图片内存占用而引发的OOM。

内存分配采用:系统匿名共享内存

2.2:渐进式呈现图片

渐进式图片格式先呈现大致的图片轮廓,然后随着图片下载的继续,呈现逐渐清晰的图片,这对于移动设备,尤其是慢网络有极大的利好,可带来更好的用户体验。

2.3:支持加载Gif图,支持WebP格式

2.4:图像的呈现

  1. 自定义居中焦点(对人脸等图片显示非常有帮助)。
  2. 圆角图,当然圆圈也行。
  3. 下载失败之后,点击重新下载。
  4. 自定义占位图,自定义overlay, 或者进度条。
  5. 指定用户按压时的overlay。

2.5:图像的加载

  1. 为同一个图片指定不同的远程路径,或者使用已经存在本地缓存中的图片。
  2. 先显示一个低解析度的图片,等高清图下载完之后再显示高清图。
  3. 加载完成回调通知。
  4. 对于本地图,如有EXIF缩略图,在大图加载完成之前,可先显示缩略图。
  5. 缩放或者旋转图片。
  6. 处理已下载的图片。

3:下载地址

Github下载地址是:https://github.com/facebook/fresco

官方使用网址:http://fresco-cn.org/docs/index.html

中文文档地址:https://www.fresco-cn.org/docs/index.html

4:支持的URI

类型 Scheme 示例
远程图片 http://, https:// HttpURLConnection
本地文件 file:// FileInputStream
Content provider content:// ContentResolver
asset目录下的资源 asset:// AssetManager
res目录下的资源 res:// Resources.openRawResource

需要注意的是:Fresco中所有的URI都必须是绝对路径,并且带上该URI的scheme

例如,要显示res/drawable下的一张图片可以使用下面的方式:

Uri uri = Uri.parse("res://aaaaa/"+R.mipmap.pic);
   
   
  • 1

上面的额”aaaaa”可以使用随意的字符串,不过还是建议使用包名来书写。

5:常用API

1:宽度不支持wrap_content, 如果要设置宽高比, 需要在Java代码中指定setAspectRatio(float ratio);

android:layout_width="20dp"
   
   
  • 1

2:高度不支持wrap_content

android:layout_height="20dp" 
   
   
  • 1

3:下载成功之前显示的图片

fresco:placeholderImage="@color/wait_color"
   
   
  • 1

4:设置图片缩放. 通常使用focusCrop,该属性值会通过算法把人头像放在中间

fresco:placeholderImageScaleType="fitCenter"
   
   
  • 1

5:加载失败的时候显示的图片

fresco:failureImage="@drawable/error"
   
   
  • 1

6:加载失败的时候图片的缩放类型

fresco:failureImageScaleType=“centerInside"
   
   
  • 1

7:加载失败,提示用户点击重新加载的图片(会覆盖failureImage的图片)

fresco:retryImage="@drawable/retrying"
   
   
  • 1

8:设置圆形方式显示图片

fresco:roundAsCircle="true"
   
   
  • 1

9:圆角设置

    fresco:roundedCornerRadius="1dp"
    fresco:roundTopLeft="true"
    fresco:roundTopRight="false"
    fresco:roundBottomLeft="false"
    fresco:roundBottomRight="true"
    fresco:roundWithOverlayColor="@color/corner_color"
    fresco:roundingBorderWidth="2dp"
    fresco:roundingBorderColor="@color/border_color"

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

6:使用步骤

6.1:添加依赖

dependencies {
  // 在 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:animated-webp:0.14.1'
  compile 'com.facebook.fresco:webpsupport:0.14.1'

  // 仅支持 WebP 静态图,需要添加
  compile 'com.facebook.fresco:webpsupport:0.14.1'
  // 其他依赖
  compile 'com.facebook.fresco:fresco:0.14.1'
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

fresco最新版本是:1.0.0

6.2:在application中初始化Fresco

Fresco.initialize(this);
   
   
  • 1

6.3:配置网络权限

<uses-permission android:name="android.permission.INTERNET"/>
   
   
  • 1

6.4:在xml布局文件中,加入命名空间

<!-- 其他元素-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent">
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6.5:在xml中引入SimpleDraweeView

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/my_image_view"
    android:layout_width="130dp"
    android:layout_height="130dp"
    fresco:placeholderImage="@drawable/my_drawable"
  />
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6.6:在Java代码中开始加载图片

Uri uri = Uri.parse("hhttp://p1.so.qhmsg.com/bdr/_240_/t01ffd622bffeabb5e1.jpg");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
   
   
  • 1
  • 2
  • 3

6.7:注意事项

如果项目中使用了OkHttp需要进行替换,

For OkHttp2:

compile "com.facebook.fresco:imagepipeline-okhttp:0.12.0+"
   
   
  • 1

For OkHttp3:

compile "com.facebook.fresco:imagepipeline-okhttp3:0.12.0+"
   
   
  • 1

7:例子

7.1:带进度条的图片

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_spimg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.bruce.chang.testfresco.FrescoSpimgActivity">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco"
        android:layout_width="150dp"
        android:layout_height="150dp"
        fresco:placeholderImage="@mipmap/fbb"
        />
    <Button
        android:id="@+id/bt_load"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="加载"
        />
</LinearLayout>

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

代码

setTitle("带进度条的图片");
        bt_load.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 设置带进度条样式
                GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
                GenericDraweeHierarchy hierarchy = builder.setProgressBarImage(new ProgressBarDrawable()).build();
                sdv_fresco.setHierarchy(hierarchy);
                Uri uri = Uri.parse("http://bizhi.zhuoku.com/bizhi/200706/4/20070625/bingbing/012.jpg");
                // 设置显示图片
                sdv_fresco.setImageURI(uri);
            }
        });
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

结果,因为布局中设置了placeholderImage,所以会加载一张默认图片

image

7.2:图片的不同裁剪

布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_crop"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        android:background="@android:color/black"
        fresco:placeholderImage="@mipmap/fbb" />
    <!--裁剪方式的描述信息-->
    <TextView
        android:id="@+id/tv_fresco_explain"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:textSize="16sp" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="48dp"
            android:orientation="vertical">
            <!--9个代表不同裁剪样式的button,这里省略-->

        </LinearLayout>
    </ScrollView>

</LinearLayout>

   
   
  • 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

代码设置

  1. GenericDraweeHierarchyBuilder的初始化
 GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
   
   
  • 1
  1. imageDisplay(加载图片的方法)
//显示图片
    private void (GenericDraweeHierarchy hierarchy) {
        sdv_fresco_crop.setHierarchy(hierarchy);
        Uri uri = Uri.parse("http://bizhi.zhuoku.com/bizhi/200706/4/20070625/bingbing/012.jpg");
        sdv_fresco_crop.setImageURI(uri);
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 9个按钮的方法
@Override
    public void onClick(View view) {
        switch (view.getId()) {
            //CENTER
            case R.id.bt_fresco_center:
                tv_fresco_explain.setText("居中,无缩放");
                //样式设置
                GenericDraweeHierarchy hierarchy = builder.setActualImageScaleType(ScalingUtils.ScaleType.CENTER).build();
                //显示图片
                imageDisplay(hierarchy);
                break;
            //CENTER_CROP
            case R.id.bt_fresco_centercrop:
                tv_fresco_explain.setText("保持宽高比缩小或放大,使得两边都大于或等于显示边界。居中显示");
                //样式设置
                GenericDraweeHierarchy hierarchy1 = builder.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP).build();
                //显示图片
                imageDisplay(hierarchy1);
                break;
            //FOCUS_CROP
            case R.id.bt_fresco_focuscrop:
                tv_fresco_explain.setText("同centerCrop, 但居中点不是中点,而是指定的某个点,这里我设置为图片的左上角那点");
                //设置focusCrop的缩放形式  并指定缩放的中心点在左上角
                PointF point = new PointF(0f, 0f);
                //样式设置
                GenericDraweeHierarchy hierarchy2 = builder.setActualImageScaleType(ScalingUtils.ScaleType.FOCUS_CROP)
                        .setActualImageFocusPoint(point)
                        .build();
                //显示图片
                imageDisplay(hierarchy2);
                break;
            //CENTER_INSIDE
            case R.id.bt_fresco_centerinside:
                tv_fresco_explain.setText("使两边都在显示边界内,居中显示。如果图尺寸大于显示边界,则保持长宽比缩小图片");
                GenericDraweeHierarchy hierarchy3 = builder.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE).build();
                imageDisplay(hierarchy3);
                break;
            //FIT_CENTER
            case R.id.bt_fresco_fitcenter:
                tv_fresco_explain.setText("保持宽高比,缩小或者放大,使得图片完全显示在显示边界内。居中显示");
                GenericDraweeHierarchy hierarchy4 = builder.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER).build();
                imageDisplay(hierarchy4);
                break;
            //FIT_START
            case R.id.bt_fresco_fitstart:
                tv_fresco_explain.setText("保持宽高比,缩小或者放大,使得图片完全显示在显示边界内,不居中,和显示边界左上对齐");
                GenericDraweeHierarchy hierarchy5 = builder.setActualImageScaleType(ScalingUtils.ScaleType.FIT_START).build();
                imageDisplay(hierarchy5);
                break;
            //FIT_END
            case R.id.bt_fresco_fitend:
                tv_fresco_explain.setText("保持宽高比,缩小或者放大,使得图片完全显示在显示边界内,不居中,和显示边界右下对齐");
                GenericDraweeHierarchy hierarchy6 = builder.setActualImageScaleType(ScalingUtils.ScaleType.FIT_END).build();
                imageDisplay(hierarchy6);
                break;
            //FIT_XY
            case R.id.bt_fresco_fitxy:
                tv_fresco_explain.setText("不保持宽高比,填充满显示边界");
                GenericDraweeHierarchy hierarchy7 = builder.setActualImageScaleType(ScalingUtils.ScaleType.FIT_XY).build();
                imageDisplay(hierarchy7);
                break;
            //null
            case R.id.bt_fresco_none:
                tv_fresco_explain.setText("不设置任何样式");
                GenericDraweeHierarchy hierarchy8 = builder.setActualImageScaleType(null).build();
                imageDisplay(hierarchy8);
                break;
            default:
                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
  • 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

结果,因为图片大小的缘故,没有完全演示,自己可以动手试试

image

7.3:圆形和圆角图片

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_circleandcorner"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/bt_fresco_circle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="设置圆形图片" />

    <Button
        android:id="@+id/bt_fresco_corner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="设置圆角图片" />

</LinearLayout>

   
   
  • 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

代码

uri = Uri.parse("http://bizhi.zhuoku.com/bizhi/200706/4/20070625/bingbing/012.jpg");
         builder = new GenericDraweeHierarchyBuilder(getResources());

        bt_fresco_circle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 参数设置为圆形
                RoundingParams params = RoundingParams.asCircle();
                GenericDraweeHierarchy hierarchy = builder.setRoundingParams(params).build();
                sdv_fresco_circleandcorner.setHierarchy(hierarchy);
                sdv_fresco_circleandcorner.setImageURI(uri);
            }
        });

        bt_fresco_corner.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 配置参数
                RoundingParams params = RoundingParams.fromCornersRadius(50f);//设置圆角大小
                params.setOverlayColor(getResources().getColor(android.R.color.holo_blue_light));//覆盖层
                params.setBorder(getResources().getColor(android.R.color.holo_blue_light), 5);//边框
//                params.setRoundAsCircle(true);//如果是RoundingParams.fromCornersRadius,这个可以强制进行圆形展示
                // 设置圆形参数
                GenericDraweeHierarchy hierarchy = builder.setRoundingParams(params).build();
                sdv_fresco_circleandcorner.setHierarchy(hierarchy);
                // 加载图片
                sdv_fresco_circleandcorner.setImageURI(uri);
            }
        });
   
   
  • 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

结果

image

7.4:渐进式显示图片

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_jpeg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.facebook.drawee.view.SimpleDraweeView
        android:layout_gravity="center"
        android:id="@+id/sdv_fresco_jpeg"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/sdv_fresco_askImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="请求网络图片" />
</LinearLayout>

   
   
  • 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

代码

builder = new GenericDraweeHierarchyBuilder(getResources());

        sdv_fresco_askImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 加载质量配置
                ProgressiveJpegConfig jpegConfig = new ProgressiveJpegConfig() {
                    @Override
                    public int getNextScanNumberToDecode(int scanNumber) {
                        return scanNumber + 2;
                    }

                    @Override
                    public QualityInfo getQualityInfo(int scanNumber) {
                        boolean isGoodEnough = (scanNumber >= 5);

                        return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false);
                    }
                };

                ImagePipelineConfig.newBuilder(FrescoJianJinShiActivity.this).setProgressiveJpegConfig(jpegConfig).build();
                // 获取图片URL
                uri = Uri.parse("http://bizhi.zhuoku.com/bizhi/200706/4/20070625/bingbing/012.jpg");

                // 获取图片请求
                ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).setProgressiveRenderingEnabled(true).build();

                DraweeController draweeController = Fresco.newDraweeControllerBuilder()
                        .setImageRequest(request)
                        .setTapToRetryEnabled(true)
                        .setOldController(sdv_fresco_jpeg.getController())//使用oldController可以节省不必要的内存分配
                        .build();

                // 设置加载的控制
                sdv_fresco_jpeg.setController(draweeController);
            }
        });
   
   
  • 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

结果

image

7.5:Gif动画图片

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_gif"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_gif"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        android:layout_gravity="center"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/bt_fresco_askImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="请求gif图片" />

    <Button
        android:id="@+id/bt_fresco_stopAnim"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="动画停止" />

    <Button
        android:id="@+id/bt_fresco_startAnim"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="动画开始" />
</LinearLayout>

   
   
  • 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

代码

  1. 请求Gif图片
bt_fresco_askImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 图片地址
                Uri uri = Uri.parse("http://www.sznews.com/humor/attachement/gif/site3/20140902/4487fcd7fc66156f51db5d.gif");
                DraweeController controller = Fresco.newDraweeControllerBuilder()
                        .setUri(uri)
                        .setAutoPlayAnimations(false)//设置为true将循环播放Gif动画
                        .setOldController(sdv_fresco_gif.getController())
                        .build();

                // 设置控制器
                sdv_fresco_gif.setController(controller);
            }
        });
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  1. 开始动画
bt_fresco_startAnim.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Animatable animation = sdv_fresco_gif.getController().getAnimatable();

                if (animation != null && !animation.isRunning()) {
                    animation.start();
                }
            }
        });
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 停止动画
 bt_fresco_stopAnim.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Animatable animation = sdv_fresco_gif.getController().getAnimatable();

                if (animation != null && animation.isRunning()) {
                    animation.stop();
                }
            }
        });
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果(不要忘了在gradle中添加gif的依赖)

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

image

7.6:多图请求以及图片复用

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_multi"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_multi"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/bt_fresco_multiImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="先显示低分辨率的图,然后是高分辨率的图"
        android:onClick="bt_fresco_multiImg_click"
        />

    <Button
        android:id="@+id/bt_fresco_thumbnailImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="本地缩略图预览"
        android:onClick="bt_fresco_thumbnailImg_click"
        />

    <Button
        android:id="@+id/bt_fresco_multiplexImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="本地图片复用"
        android:onClick="bt_fresco_multiplexImg_click"
        />

</LinearLayout>

   
   
  • 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

代码

  1. 先显示低分辨率的图,然后是高分辨率的图
void bt_fresco_multiImg_click(View view) {
        //同一张图片,不同品质的两个uri
        Uri lowResUri = Uri.parse("http://img1.gamedog.cn/2012/03/11/19-120311133617-50.jpg");
        Uri highResUri = Uri.parse("http://img5.duitang.com/uploads/item/201312/03/20131203153823_Y4y8F.jpeg");
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setLowResImageRequest(ImageRequest.fromUri(lowResUri))
                .setImageRequest(ImageRequest.fromUri(highResUri))
                .setOldController(sdv_fresco_multi.getController())
                .build();
        sdv_fresco_multi.setController(controller);
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 本地缩略图预览
void bt_fresco_thumbnailImg_click(View view){

        //将本地图片地址转换成Uri
        Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/swj.jpg"));
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setLocalThumbnailPreviewsEnabled(true)
                .build();
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setOldController(sdv_fresco_multi.getController())
                .build();
        sdv_fresco_multi.setController(controller);
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. 本地图片复用
void bt_fresco_multiplexImg_click(View view){

        //本地图片的复用
        //在请求之前,还会去内存中请求一次图片,没有才会先去本地,最后去网络uri

        //本地准备复用图片的uri  如果本地这个图片不存在,会自动去加载下一个uri
        Uri uri1 = Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/swj.jpg"));
        //图片的网络uri
        Uri uri2 = Uri.parse("http://img5.duitang.com/uploads/item/201312/03/20131203153823_Y4y8F.jpeg");
        ImageRequest request1 = ImageRequest.fromUri(uri1);
        ImageRequest request2 = ImageRequest.fromUri(uri2);
        ImageRequest[] requests = {request1, request2};
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setFirstAvailableImageRequests(requests)
                .setOldController(sdv_fresco_multi.getController())
                .build();
        sdv_fresco_multi.setController(controller);
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

结果

image

7.7:图片加载监听

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_listener"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <com.facebook.drawee.view.SimpleDraweeView
        android:layout_gravity="center"
        android:id="@+id/sdv_fresco_listener"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/bt_fresco_listener"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="开始加载图片"
        android:onClick="bt_fresco_listener_click"
        />

    <TextView
        android:id="@+id/tv_fresco_listener"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="14sp"
        android:text="tv_fresco_listener"
        />

    <TextView
        android:id="@+id/tv_fresco_listener2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="14sp"
        android:text="tv_fresco_listener2"
        />
</LinearLayout>

   
   
  • 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

代码

  1. 自定义BaseControllerListener初始化
//对所有的图片加载,onFinalImageSet 或者 onFailure 都会被触发。前者在成功时,后者在失败时。
    //如果允许呈现渐进式JPEG,同时图片也是渐进式图片,onIntermediateImageSet会在每个扫描被解码后回调。
    // 具体图片的那个扫描会被解码,参见渐进式JPEG图
    private ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
        @Override
        public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
           //前者在成功时
            super.onFinalImageSet(id, imageInfo, animatable);

            if (imageInfo == null) {
                return;
            }

            QualityInfo qualityInfo = imageInfo.getQualityInfo();

            tv_fresco_listener.setText("Final image received! " +
                    "\nSize: " + imageInfo.getWidth()
                    + "x" + imageInfo.getHeight()
                    + "\nQuality level: " + qualityInfo.getQuality()
                    + "\ngood enough: " + qualityInfo.isOfGoodEnoughQuality()
                    + "\nfull quality: " + qualityInfo.isOfFullQuality());
        }

        @Override
        public void onIntermediateImageSet(String id, ImageInfo imageInfo) {
            super.onIntermediateImageSet(id, imageInfo);

            tv_fresco_listener2.setText("IntermediateImageSet image receiced");
        }
        //后者在失败时
        @Override
        public void onFailure(String id, Throwable throwable) {
            super.onFailure(id, throwable);

            tv_fresco_listener.setText("Error loading" + id);
        }
    };
   
   
  • 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
  1. 开始加载图片按钮方法
void bt_fresco_listener_click(View view) {

        ProgressiveJpegConfig jpegConfig = new ProgressiveJpegConfig() {
            @Override
            public int getNextScanNumberToDecode(int scanNumber) {
                return scanNumber + 2;
            }

            @Override
            public QualityInfo getQualityInfo(int scanNumber) {
                boolean isGoodEnough = (scanNumber >= 5);

                return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false);
            }
        };

        ImagePipelineConfig.newBuilder(this).setProgressiveJpegConfig(jpegConfig).build();
        Uri uri = Uri.parse("http://h.hiphotos.baidu.com/zhidao/pic/item/58ee3d6d55fbb2fbac4f2af24f4a20a44723dcee.jpg");
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).setProgressiveRenderingEnabled(true).build();

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setOldController(sdv_fresco_listener.getController())
                .setImageRequest(request)
                //设置监听器监听图片加载状态
                .setControllerListener(controllerListener)
                .build();

        sdv_fresco_listener.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

结果,加载成功的时候可以得到图片的相关信息,如Size,在浏览器中查看,该图片的尺寸就是那么大的。

image

7.8:图片缩放和旋转

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_resize"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_resize"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/bt_fresco_resize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:onClick="bt_fresco_resize_click"
        android:text="修内存中改图片大小" />

    <Button
        android:id="@+id/bt_fresco_rotate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="bt_fresco_rotate_click"
        android:text="旋转图片" />

</LinearLayout>

   
   
  • 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

代码

//缩放
    void bt_fresco_resize_click(View view) {

        int width = 50;
        int height = 50;
        Uri uri = Uri.parse("http://c.hiphotos.baidu.com/image/pic/item/962bd40735fae6cd21a519680db30f2442a70fa1.jpg");
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setResizeOptions(new ResizeOptions(width, height)).build();
        PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                .setOldController(sdv_fresco_resize.getController())
                .setImageRequest(request)
                .build();
        sdv_fresco_resize.setController(controller);
    }

    //旋转
    void bt_fresco_rotate_click(View view) {
        Uri uri2 = Uri.parse("http://c.hiphotos.baidu.com/image/pic/item/962bd40735fae6cd21a519680db30f2442a70fa1.jpg");
        RotationOptions rotationOptions = RotationOptions.forceRotation(RotationOptions.ROTATE_90);
        ImageRequest request1 = ImageRequestBuilder.newBuilderWithSource(uri2)
                .setRotationOptions(RotationOptions.autoRotate())
                .setRotationOptions(rotationOptions)//旋转的时候要使用RotationOptions类
                .build();//但貌似Fresco在旋转的功能上不是很好
        DraweeController controller1 = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request1)
                .setOldController(sdv_fresco_resize.getController()).build();
        sdv_fresco_resize.setController(controller1);
    }
   
   
  • 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

结果

image

7.9:修改图片

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_modify"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_modify"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@mipmap/fbb" />

    <Button
        android:id="@+id/bt_fresco_modify"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="为图片添加网格"
        android:onClick="bt_fresco_modify_click"
        />
</LinearLayout>

   
   
  • 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

代码

void bt_fresco_modify_click(View view){

        Uri uri = Uri.parse("http://c.hiphotos.baidu.com/image/pic/item/962bd40735fae6cd21a519680db30f2442a70fa1.jpg");

        Postprocessor redMeshPostprocessor = new BasePostprocessor() {
            @Override
            public String getName() {
                return "redMeshPostprocessor";
            }
            //绘制红色点状网格
            @Override
            public void process(Bitmap bitmap) {

                for (int x = 0; x < bitmap.getWidth(); x += 2) {

                    for (int y = 0; y < bitmap.getHeight(); y += 2) {
                        bitmap.setPixel(x, y, Color.RED);
                    }
                }
            }
        };
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setPostprocessor(redMeshPostprocessor)
                .build();
        PipelineDraweeController controller = (PipelineDraweeController)
                Fresco.newDraweeControllerBuilder()
                        .setImageRequest(request)
                        .setOldController(sdv_fresco_modify.getController())
                        .build();
        sdv_fresco_modify.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
  • 30
  • 31

结果

image

7.10:

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_auto_size"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <Button
        android:id="@+id/bt_fresco_loadsmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="加载图片"
        android:onClick="bt_fresco_loadsmall_click"
        />

    <LinearLayout
        android:id="@+id/ll_fresco"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:orientation="vertical">

    </LinearLayout>
</LinearLayout>

   
   
  • 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

代码

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fresco_dynamic_display_img);
        ll_fresco = (LinearLayout) findViewById(R.id.ll_fresco);
        setTitle("动态展示图片");

        simpleDraweeView = new SimpleDraweeView(this);
        //设置宽高比
        simpleDraweeView.setAspectRatio(1.0f);
    }

    void bt_fresco_loadsmall_click(View view) {

        final Uri uri = Uri.parse("http://img4q.duitang.com/uploads/item/201304/27/20130427043538_wAfHC.jpeg");

        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .build();

        PipelineDraweeController controller = (PipelineDraweeController)
                Fresco.newDraweeControllerBuilder()
                        .setImageRequest(request)
                        .setOldController(simpleDraweeView.getController())
                        .build();
        simpleDraweeView.setController(controller);
        ll_fresco.addView(simpleDraweeView);
    }
   
   
  • 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

结果

image

8:注意事项

8.1:问题处理

  1. 重复的边界
这是使用圆角的一个缺陷。 参考圆角和圆圈 来获取更多信息。
   
   
  • 1
  1. 图片没有加载
你可以从 image pipeline 打出的日志来查看原因。 这里提供一些通常会导致问题的原因:
   
   
  • 1
  1. 文件不可用
无效的路径、链接会导致这种情况。
判断网络链接是否有效,你可以尝试在浏览器中打开它,看看是否图片会被加载。若图片依然加载不出来,那么这不是Fresco的问题。
判断本地文件是否有效,你可以通过下面这段代码来校验:

FileInputStream fis = new FileInputStream(new File(localUri.getPath()));

如果这里抛出了异常,那么这不是Fresco的问题,可能是你的其他代码导致的。有可能是没有获取到SD卡读取权限、路径不合法、文件不存在等。
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. OOM - 无法分配图片空间
加载特别特别大的图片时最容易导致这种情况。
如果你加载的图片比承载的View明显大出太多,那你应该考虑将它Resize一下。
   
   
  • 1
  • 2
  1. Bitmap太大导致无法绘制
Android 无法绘制长或宽大于2048像素的图片。
这是由OpenGL渲染系统限制的,如果它超过了这个界限,Fresco会对它进行Resize
   
   
  • 1
  • 2
  1. 通过Logcat来判断原因
在加载图片时会出现各种各样的原因导致加载失败。
在使用Fresco的时候,最直接的方式就是查看 image pipeline 打出的VERBOSE级别日志。
   
   
  • 1
  • 2
  1. 启动日志
默认情况下Fresco是关闭日志输出的,你可以配置image pipeline让它启动.

Set<RequestListener> requestListeners = new HashSet<>();
requestListeners.add(new RequestLoggingListener());
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
   // other setters
   .setRequestListeners(requestListeners)
   .build();
Fresco.initialize(context, config);
FLog.setMinimumLoggingLevel(FLog.VERBOSE);
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 查看日志
你可以通过下面这条shell命令来查看Fresco日志:

adb logcat -v threadtime | grep -iE 'LoggingListener|AbstractDraweeController|BufferedDiskCache'

它的输出为如下格式:
08-12 09:11:14.792 6690 6734 V unknown:RequestLoggingListener: time 11201792: onProducerStart: {requestId: 1, producer: EncodedMemoryCacheProducer}
08-12 09:11:14.792 6690 6734 V unknown:RequestLoggingListener: time 11201792: onProducerFinishWithSuccess: {requestId: 1, producer: EncodedMemoryCacheProducer, elapsedTime: 0 ms, extraMap: {cached_value_found=false}}
08-12 09:11:14.792 6690 6734 V unknown:RequestLoggingListener: time 11201792: onProducerStart: {requestId: 1, producer: DiskCacheProducer}
08-12 09:11:14.792 6690 6735 V unknown:BufferedDiskCache: Did not find image for http://www.example.com/image.jpg in staging area
08-12 09:11:14.793 6690 6735 V unknown:BufferedDiskCache: Disk cache read for http://www.example.com/image.jpg
08-12 09:11:14.793 6690 6735 V unknown:BufferedDiskCache: Disk cache miss for http://www.example.com/image.jpg
08-12 09:11:14.793 6690 6735 V unknown:RequestLoggingListener: time 11201793: onProducerFinishWithSuccess: {requestId: 1, producer: DiskCacheProducer, elapsedTime: 1 ms, extraMap: {cached_value_found=false}}
08-12 09:11:14.793 6690 6735 V unknown:RequestLoggingListener: time 11201793: onProducerStart: {requestId: 1, producer: NetworkFetchProducer}
08-12 09:11:15.161 6690 7358 V unknown:RequestLoggingListener: time 11202161: onProducerFinishWithSuccess: {requestId: 1, producer: NetworkFetchProducer, elapsedTime: 368 ms, extraMap: null}
08-12 09:11:15.162 6690 6742 V unknown:BufferedDiskCache: About to write to disk-cache for key http://www.example.com/image.jpg
08-12 09:11:15.162 6690 6734 V unknown:RequestLoggingListener: time 11202162: onProducerStart: {requestId: 1, producer: DecodeProducer}
08-12 09:11:15.163 6690 6742 V unknown:BufferedDiskCache: Successful disk-cache write for key http://www.example.com/image.jpg
08-12 09:11:15.169 6690 6734 V unknown:RequestLoggingListener: time 11202169: onProducerFinishWithSuccess: {requestId: 1, producer: DecodeProducer, elapsedTime: 7 ms, extraMap: {hasGoodQuality=true, queueTime=0, bitmapSize=600x400, isFinal=true}}
08-12 09:11:15.169 6690 6734 V unknown:RequestLoggingListener: time 11202169: onRequestSuccess: {requestId: 1, elapsedTime: 378 ms}
08-12 09:11:15.184 6690 6690 V unknown:AbstractDraweeController: controller 28ebe0eb 1: set_final_result @ onNewResult: image: CloseableReference 2fd41bb0

在这个示例中,我们发现名为28ebe0eb的 DraweeView 向名为36e95857的 DataSource 进行了图像请求。
首先,图片没有在内存缓存中找到,也没有在磁盘缓存中找到,最后去网络上下载图片。下载成功后,图片被解码,之后请求结束。
最后数据源通知 controller 图片就绪,显示图片(set_final_result)。

   
   
  • 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

8.2:一些陷阱

  1. 不要使用 ScrollViews界
如果你想要在一个长的图片列表中滑动,你应该使用 RecyclerView,ListView,或 GridView。这三者都会在你滑动时不断重用子视图。Fresco 的 view 会接收系统事件,使它们能正确管理内存。
ScrollView 不会这样做。因此,Fresco view 不会被告知它们是否在屏幕上显示,并保持图片内存占用直到你的 Fragment 或 Activity 停止。
你的 App 将会面临更大的 OOM 风险。
   
   
  • 1
  • 2
  • 3
  1. 不要向下转换
不要试图把Fresco返回的一些对象进行向下转化,这也许会带来一些对象操作上的便利
,但是也许在后续的版本中,你会遇到一些因为向下转换特性丢失导致的难以处理的问题。
   
   
  • 1
  • 2
  1. 不要使用getTopLevelDrawable
DraweeHierarchy.getTopLevelDrawable() 仅仅 应该在DraweeViews中用,除了定义View中,其他应用代码建议连碰都不要碰这个。

在自定义view中,也千万不要将返回值向下转换,也许下个版本,我们会更改这个返回值类型。
   
   
  • 1
  • 2
  • 3
  1. 不要复用 DraweeHierarchies
永远不要把 DraweeHierarchy 通过 DraweeView.setHierarchy 设置给不同的View。
DraweeHierarchy 是由一系列 Drawable 组成的。在 Android 中, Drawable 不能被多个 View 共享。
   
   
  • 1
  • 2
  1. 不要在多个DraweeHierarchy中使用同一个Drawable
原因同上。不过你可以在占位图、重试图、错误图中使用相同的资源ID,Android 实际会创建不同的 Drawable。

如果你使用GenericDraweeHierarchyBuilder,那么需要调用Resources.getDrawable来通过资源获取图片。

不过请不要只调用一次然后将结果传给不同的Hierarchy!
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 不要直接控制 hierarchy
不要直接使用 SettableDraweeHierarchy 方法(reset,setImage,…)。

它们应该仅由 controller 使用。

不要使用setControllerOverlay来设置一个覆盖图,这个方法只能给 controller 调用。
如果你需要显示覆盖图,可以参考Drawee的各种效果配置
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 不要直接给 DraweeView 设置图片
目前 DraweeView 直接继承于 ImageView,因此它有 setImageBitmap,
setImageDrawable 等方法。
如果利用这些方法直接设置一张图片,内部的 DraweeHierarchy 就会丢失,也就无法取到image
pipeline 的任何图像了。
   
   
  • 1
  • 2
  • 3
  • 4
  1. 使用 DraweeView 时,请不要使用任何 ImageView 的属性
在后续的版本中,DraweeView 会直接从 View 派生。
任何属于 ImageView 但是不属于 View 的方法都会被移除。

   
   
  • 1
  • 2
  • 3

8.3:为什么不支持wrap_content

人们经常会问,为什么Fresco中不可以使用wrap_content?

主要的原因是,Drawee永远会在getIntrinsicHeight/getIntrinsicWidth中返回-1。
这么做的原因是 Drawee 不像ImageView一样。它同一时刻可能会显示多个元素。比如在从占位图渐变到目标图
时,两张图会有同时显示的时候。再比如可能有多张目标图片(低清晰度、高清晰度两张)。如果这些图像都是不同的尺寸,那么很难定义”intrinsic”尺寸。

如果我们要先用占位图的尺寸,等加载完成后再使用真实图的尺寸,那么图片很可能显
示错误。它可能会被根据占位图的尺寸来缩放、裁剪。
唯一防止这种事情的方式就只有在图片加载完成后强制触发一次layout。这样的话不仅
会影响性能,而且会让应用的界面突变,很影响用户体验!
如果用户正在读一篇文章,然后在图片加载完成后整篇文章突然向下移动,这是非常不好的。

所以你必须指定尺寸或者用match_parent来布局。

你如果从服务端请求图片,服务端可以做到返回图片尺寸。然后你拿到之后通过setLayoutParams 来给View设置宽高。

当然如果你必须要使用wrap_content,那么你可以参考StackOverflow上的一个回答。
但是我们以后会移除这个功能,Ugly things should look ugly。
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

8.4:共享元素动画

使用 ChangeBounds,而不是ChangeImageTransform

Android 5.0 (Lollipop) 引入了 共享元素动画,允许在多个Activity切换时共享相同的View!

你可以在XML中定义这个变换。有个ChangeImageTransform变换可以在共享元素切换时对ImageView进行变换,可惜Fresco暂时不支持它,因为Drawee维护着自己的转换Matrix。

幸运的是你可以有另一种做法:使用ChangeBounds。你可以改变layout的边界,这样Fresco会根据它进行自适应,也能够达到你想要的功能。
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

9:总结

Fresco的使用在一定程度上要比Picasso、GLide要复杂,但是在强大的Fresco面前,复杂并不是理由,只要灵活的使用Fresco,一定会给我们的开发带来便利。

有关Fresco的任何问题可以查看Fresco的中文API网址来寻求解决方案。

https://www.fresco-cn.org/docs/index.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值