Android图片加载库—Fresco一个强大的图片加载组件

Fresco是一个支持Android2.3及以上的强大图片加载组件,其特色在于Image Pipeline设计和三级缓存机制。通过SimpleDraweeView控件,可以方便地进行图片加载、设置占位图、调整缩放类型等。Fresco还支持渐进式加载,提高用户体验。在初始化Fresco并配置权限后,可在XML布局或Java代码中使用SimpleDraweeView实现图片加载和自定义显示效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

GitHub源码 (点击查看)

这里写图片描述
这里写图片描述
这里写图片描述
Fresco支持Android2.3(API level 9)及其以上系统。

依赖

由于我用的是android studio所以这里就只是说一下android studio下如何配置,在强大的gradle,只需要一句话搞定,gradle会帮你下载这个Fresco框架,gradle真好,可以自动维护你项目中的框架

compile 'com.facebook.fresco:fresco:0.5.0+'
dependencies {
  // 其他依赖
  compile 'com.facebook.fresco:fresco:0.12.0'
}

下面的依赖需要根据需求添加:

dependencies {
  // 在 API < 14 上的机器支持 WebP 时,需要添加
  compile 'com.facebook.fresco:animated-base-support:0.12.0'

  // 支持 GIF 动图,需要添加
  compile 'com.facebook.fresco:animated-gif:0.12.0'

  // 支持 WebP (静态图+动图),需要添加
  compile 'com.facebook.fresco:animated-webp:0.12.0'
  compile 'com.facebook.fresco:webpsupport:0.12.0'

  // 仅支持 WebP 静态图,需要添加
  compile 'com.facebook.fresco:webpsupport:0.12.0'
}

最牛特性 查看

这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述
Fresco的image pipeline 【 ˈpaɪplaɪn】 设计
这里写图片描述

详细的用法,点击查看

Demo栗子第1颗

fresco搭建开发环境

gradle
compile 'com.facebook.fresco:fresco:0.12.0'

清单文件配置

public class FrescoApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //初始化Fresco框架
        Fresco.initialize(this);
    }
}

配置权限

    <!--网络-->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--sd卡-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

布局

 <com.facebook.drawee.view.SimpleDraweeView
        android:layout_width="100dp"
        android:layout_margin="5dp"
        android:background="#AEAEAE"
        android:src="@mipmap/ic_launcher"
        android:id="@+id/image"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:scaleType="centerCrop"
        fresco:roundedCornerRadius="10dp"
        fresco:roundTopLeft="true"
        fresco:roundTopRight="true"
        fresco:roundBottomLeft="true"
        fresco:roundBottomRight="true"
        android:layout_height="100dp" />

编码实现


public class MainActivity extends AppCompatActivity {

    private SimpleDraweeView simpleDraweeView;
    private String url;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //(fresco:由facebook公司出的,一种图片三级缓存的实现.)
        //步骤二。使用fresco加载网络图片
        //2.1.准备一个图片的网络地址
        url = "http://img3.imgtn.bdimg.com/it/u=3376426628,3397639127&fm=11&gp=0.jpg";
        //2.2 布局fresco 的自定义控件 (必须给控件设置大小)
        simpleDraweeView = (SimpleDraweeView) findViewById(R.id.image);
        //2.4.自定义控件的相关属性  可以设置圆角。
        //  fresco:roundedCornerRadius="10dp"
        //  fresco:roundTopLeft="true"
        //  fresco:roundTopRight="true"
        //  fresco:roundBottomLeft="true"
        //  fresco:roundBottomRight="true"
    }
    public void showImage(View view) {
        //2.3.加载图片
        simpleDraweeView.setImageURI(url);
    }
}

Demo栗子第2颗

如果你仅仅是想简单下载一张网络图片,在下载完成之前,显示一张占位图,那么简单使用 SimpleDraweeView 即可。
在加载图片之前,你必须初始化Fresco类。你只需要调用Fresco.initialize一次即可完成初始化,在 Application 里面做这件事再适合不过了(如下面的代码),注意多次的调用初始化是无意义的。

[MyApplication.java]
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Fresco.initialize(this);
    }
}

做完上面的工作后,你需要在 AndroidManifest.xml 中指定你的 Application 类。为了下载网络图片,请确认你声明了网络请求的权限。

 <manifest
    ...
    >
    <uses-permission android:name="android.permission.INTERNET" />
    <application
      ...
      android:label="@string/app_name"
      android:name=".MyApplication"
      >
      ...
    </application>
    ...
  </manifest>

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

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

开始加载图片:

Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);

方法栗子:

SimpleDraweeView控件

SimpleDraweeView这个控件了,显示图片的时候直接写了一个setImageURI(uri)

在xml中引入SimpleDraweeView

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/user_avator"
    android:layout_width="50dp"
    android:layout_height="50dp"
    fresco:roundAsCircle="true"
    fresco:roundedCornerRadius="180dp"
    fresco:actualImageScaleType="focusCrop"
    android:layout_centerVertical="true" />

注意:1、属性中存在fresco:开头的声明。这个是fresco的自定义属性,如果我们需要使用其自定义属性,必须在我们的xml根布局中添加声明/命名空间

<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:orientation="vertical">

2、配置网络权限
3、在Java代码中开始加载图片

Uri uri = Uri.parse("https://raw.githubusercontent.com/static/fresco-logo.png");  
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);  
draweeView.setImageURI(uri);  

接下来详细研究其用法:

URIs的使用:

类型  Scheme  示例
远程图片    http://, https://   HttpURLConnection 或者参考 使用其他网络加载方案
本地文件    file:// FileInputStream
Content provider    content://  ContentResolver
asset目录下的资源 asset://    AssetManager
res目录下的资源   res://  Resources.openRawResource
res 示例:Uri uri = Uri.parse("res://包名(实际可以是任何字符串甚至留空)/" + R.drawable.ic_launcher);

注意:Fresco 不支持 相对路径的URI. 所有的URI都必须是绝对路径,并且带上该URI的scheme。

在XML中使用SimpleDraweeView:

给出一个完整的示例:

<com.facebook.drawee.view.SimpleDraweeView  
    android:id="@+id/my_image_view"  
    android:layout_width="20dp"  / 不支持wrap_content 如果要设置宽高比, 需要在Java代码中指定setAspectRatio(1.33f);
    android:layout_height="20dp"  // 不支持wrap_content 
    fresco:fadeDuration="300"//渐进时间  
    fresco:actualImageScaleType="focusCrop"   // 设置图片缩放. 通常使用focusCrop,该属性值会通过算法把人头像放在中间
    fresco:placeholderImage="@color/wait_color"  
    fresco:placeholderImageScaleType="fitCenter"  
    fresco:failureImage="@drawable/error"//失败时显示的图片  
    fresco:failureImageScaleType="centerInside"//失败图片的显示方式  
    fresco:retryImage="@drawable/retrying"//重试图  
    fresco:retryImageScaleType="centerCrop"//重试图显示方式  
    fresco:progressBarImage="@drawable/progress_bar"  
    fresco:progressBarImageScaleType="centerInside"  
    fresco:progressBarAutoRotateInterval="1000"  
    fresco:backgroundImage="@color/blue"  
    fresco:overlayImage="@drawable/watermark"  
    fresco:pressedStateOverlayImage="@color/red"  

    fresco:roundAsCircle="false"// 是不是设置圆圈  
    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"  
  />  

说明:必须声明 android:layout_width 和 android:layout_height,否则将无法正确加载图像,另外不支持 wrap_content 属性,但也有例外的时候,如果想固定控件的宽高比,则可以使用wrap_content,并通过在xml代码中设置fresco:viewAspectRatio=”小数”或者在Java代码中设置mSimpleDraweeView.setAspectRatio(1.33f);即可。
在Java中自定义显示图

一般情况下,在XML设置显示效果即可, 如果想更多定制化,可以这样:

创建一个 builder 然后设置给 SimpleDraweeView:

List<Drawable> backgroundsList;  
List<Drawable> overlaysList;  
GenericDraweeHierarchyBuilder builder =  
    new GenericDraweeHierarchyBuilder(getResources());  
GenericDraweeHierarchy hierarchy = builder  
    .setFadeDuration(300)  
    .setPlaceholderImage(new MyCustomDrawable())  
    .setBackgrounds(backgroundList)  
    .setOverlays(overlaysList)  
    .build();  
mSimpleDraweeView.setHierarchy(hierarchy);  

注意:请不要多次调用setHierarchy,即使这个View是可回收的。创建 DraweeHierarchy 的较为耗时的一个过程,应该多次利用。

  • 修改 DraweeHierarchy

DraweeHierarchy 的一些属性可以在运行时改变。

要改变这些属性,首先获取一个引用:

GenericDraweeHierarchy hierarchy = mSimpleDraweeView.getHierarchy();

  • 修改占位图

修改占位图为资源id:hierarchy.setPlaceholderImage(R.drawable.placeholderId);

或者修改为一个 Drawable:Drawable drawable; hierarchy.setPlaceholderImage(drawable);

  • 修改缩放类型

hierarchy.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE);

如果你选择缩放类型为 focusCrop,需要指定一个居中点:hierarchy.setActualImageFocusPoint(point);

  • 修改图片尺寸
Uri uri = "file:///mnt/sdcard/MyApp/myfile.jpg";
int width = 50, height = 50;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setResizeOptions(new ResizeOptions(width, height))
    .build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
    .setOldController(mDraweeView.getController())
    .setImageRequest(request)
    .build();
mSimpleDraweeView.setController(controller);
  • 自动旋转
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setAutoRotateEnabled(true)
    .build();

setController(controller)方法加载图片

DraweeController controller = Fresco.newDraweeControllerBuilder().setUri(uri).build();
        imageView.setController(controller);

当然如果你想监听加载的过程,就加一个ControllerListen

ControllerListener listener = new BaseControllerListener(){
            @Override
            public void onFinalImageSet(String id, Object imageInfo, Animatable animatable) {
                super.onFinalImageSet(id, imageInfo, animatable);
            }

            @Override
            public void onFailure(String id, Throwable throwable) {
                super.onFailure(id, throwable);
            }

            @Override
            public void onIntermediateImageFailed(String id, Throwable throwable) {
                super.onIntermediateImageFailed(id, throwable);
            }
        };
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(uri)
                .setControllerListener(listener)
                .build();
        imageView.setController(controller);

图片加载成功或者失败,会执行里面的方法,其中图片加载成功时会执行onFinalImageSet方法,图片加载失败时会执行onFailure方法,如果图片设置渐进式,onIntermediateImageFailed会被回调

说完了如何加载uri之后,如何实现在xml中的效果呢?我们继续在java代码中实现xml的效果

GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources())
                .setFadeDuration(300)
                .setBackground(getDrawable(R.drawable.ic_launcher))
                .setPlaceholderImage(getDrawable(R.drawable.ic_launcher))
                .setFailureImage(getDrawable(R.drawable.ic_launcher))
                .build();
        imageView.setHierarchy(hierarchy);

方法很多,你在xml中用到的都可以在这里设置,有些在xml中不能设置的在这里也是可以的,例如,我可以设置多张背景图片,我可以设置多张叠加图,这里都可以帮你实现,是不是很强大啊,想不想拿到特权了一样呢!但是DraweeHiererchy创建时比较耗时,所以要多次利用

GenericDraweeHierarchy hierarchy1 = imageView.getHierarchy();

首先是渐进式图片加载,这方面的功能充分考虑了网络比较慢的情况下,用户不至于一致在等,最起码能看到模糊的照片,这个所谓的渐进式加载就是说用户从图片加载之后,图片会从模糊到清晰的一个渐变过程,当然这个过程仅限于从网络加载图片,本地或者缓存等地方的图片也不需要渐进式加载,没有意义

ProgressiveJpegConfig config = new ProgressiveJpegConfig() {
            @Override
            public int getNextScanNumberToDecode(int i) {
                return 0;
            }

            @Override
            public QualityInfo getQualityInfo(int i) {
                return null;
            }
        };

        ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
                .setProgressiveJpegConfig(config)
                .build();
        Fresco.initialize(getApplicationContext(),imagePipelineConfig);

当然你也可以使用ProgressiveJpegConfig config1= new SimpleProgressiveJpegConfig(list,2);

<pre name="code" class="java">FLog.setMinimumLoggingLevel(FLog.VERBOSE);
        Set<RequestListener> listeners = new HashSet<>();
        listeners.add(new RequestLoggingListener());
        ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
                .setRequestListeners(listeners)
                .build();
        Fresco.initialize(this, config);
        setContentView(R.layout.activity_main);

        mProgressiveJpegView = (SimpleDraweeView) findViewById(R.id.my_image_view);

        Uri uri = Uri.parse("http://pooyak.com/p/progjpeg/jpegload.cgi?o=1");
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setProgressiveRenderingEnabled(true)
                .build();
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .build();
        mProgressiveJpegView.setController(controller);
ImageRequest request = ImageRequestBuilder
                .newBuilderWithSource(uri)
                .setProgressiveRenderingEnabled(true)
                .build();
        PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setOldController(imageView.getController())
                .build();
        imageView.setController(controller);

个人认为这个框架最巧妙的地方,就是把bitmap保存到ashmen,不会启动gc,使的界面不会因为gc而卡死,Fresco使用三级缓存,第一级缓存就是保存bitmap,第二级缓存保存在内存,但是没有解码,使用时需要界面,第三级缓存就是保存在本地文件,同样文件也未解码,使用的时候要先解码啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值