Fresco_android中图片加载的神器

使用原因

最近工作需要在4.4的开发板上开发软件,并且需要展示大量的图片.
平时一直使用的图片加载框架是Picasso,但是Fresco在4.4以下使用的黑科技让人不得不心动.
Fresco在android4.4以下版本时,图片使用的内存空间是在匿名类的内存空间,极大的减少内存空间占用,从而可以让你摆脱99%由于图片造成的OOM,真乃神器(外挂)也~~

作用:
显示占位图直到加载完成;
下载图片
缓存图片
图片不再显示时,从内存中移除;

导包

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

    按需求添加:
    // 在 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'

基本使用

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"  //添加fresco的命名空间
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.junx.fresco.MainActivity">
    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/my_image_view"
        android:layout_width="300dp" //不支持wrap_content
        android:layout_height="wrap_content"//但可以配合fresco:viewAspectRatio属性
        fresco:viewAspectRatio="1.33"
        fresco:placeholderImage="@mipmap/ic_launcher_round"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent" android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="8dp" app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp"/>

</android.support.constraint.ConstraintLayout>
iv = (SimpleDraweeView) findViewById(R.id.my_image_view);
        /*远程图片              http://, https://   HttpURLConnection 或者参考 使用其他网络加载方案
        本地文件                    file:// FileInputStream
        Content provider        content://  ContentResolver
        asset目录下的资源     asset://    AssetManager
        res目录下的资源           res://  Resources.openRawResource
        Uri中指定图片数据      data:mime/type;base64,  数据类型必须符合 rfc2397规定 (仅支持 UTF-8)

        Uri uri = Uri.parse("res://包名(实际可以是任何字符串甚至留空)/" + R.drawable.ic_launcher)
        */
        //fresco不支持相对路径,必须为绝对路径
        iv.setImageURI(pic_umr);

XML中属性的使用

<com.facebook.drawee.view.SimpleDraweeView
  android:id="@+id/my_image_view"
  android:layout_width="20dp" //不支持wrap_content,但可以配合fresco:viewAspectRatio使用
  android:layout_height="20dp"
  fresco:fadeDuration="300"
  fresco:actualImageScaleType="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"
/>

代码中设置属性

    //动态设置属性,应该在设置uri前进行
    private GenericDraweeHierarchy setAttrs() {
        //圆角属性,只有BitmapDrawable 和 ColorDrawable类的图片可以实现圆角。
        RoundingParams roundingParams = RoundingParams.fromCornersRadius(7f);
        roundingParams.setRoundAsCircle(true);
        //设置外层的颜色,默认为透明
        roundingParams.setOverlayColor(Color.TRANSPARENT);

        GenericDraweeHierarchyBuilder builder =new GenericDraweeHierarchyBuilder(getResources());
        GenericDraweeHierarchy hierarchy = builder
                .setRoundingParams(roundingParams)
                //图片缓缓展示出来
                .setFadeDuration(3000)
                .setPlaceholderImage(R.mipmap.ic_launcher_round)
                .setFailureImage(R.mipmap.ic_launcher)
//                .setOverlays(overlaysList)
                .build();
        iv.setHierarchy(hierarchy);
        return hierarchy;
    }
    //一部分属性可以动态修改
    private  void changeParams(){
        //也可以通过控件获取
        GenericDraweeHierarchy hierarchy = iv.getHierarchy();
        //图层类的可以修改
        hierarchy.setPlaceholderImage(R.mipmap.ic_launcher_round);
        //修改缩放类型
        hierarchy.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE);
        //如果你选择缩放类型为 focusCrop,需要指定一个居中点
        hierarchy.setActualImageFocusPoint(new PointF(50,50));
        //可以为图像添加一个 color filter
        hierarchy.setActualImageColorFilter(new ColorFilter());
        //修改圆角显示方式,当圆角不能改为圆圈
        RoundingParams roundingParams = hierarchy.getRoundingParams();
        roundingParams.setCornersRadius(10);
        hierarchy.setRoundingParams(roundingParams);
    }

各种效果设置

    //通过Controller来设置更多hierarchy不能设置的属性
    private void setController() {
        ControllerListener listener = new BaseControllerListener(){
            @Override
            public void onSubmit(String id, Object callerContext) {
                super.onSubmit(id, callerContext);
            }

            @Override
            public void onFinalImageSet(String id, Object imageInfo, Animatable animatable) {
                super.onFinalImageSet(id, imageInfo, animatable);
                Log.v("meee",getClass()+":\n"+"加载成功时触发");
            }

            //如果允许呈现渐进式JPEG,同时图片也是渐进式图片,onIntermediateImageSet会在每个扫描被解码后回调。
            @Override
            public void onIntermediateImageSet(String id, Object imageInfo) {
                super.onIntermediateImageSet(id, imageInfo);
            }

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

            @Override
            public void onFailure(String id, Throwable throwable) {
                super.onFailure(id, throwable);
                Log.v("meee",getClass()+":\n"+"失败");
            }

            @Override
            public void onRelease(String id) {
                super.onRelease(id);
            }
        };

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(pic_umr)
                //点击重试,默认失败时会重试4次,
                .setTapToRetryEnabled(true)
                //在指定一个新的controller的时候,使用setOldController,这可节省不必要的内存分配
                .setOldController(iv.getController())
                //设置Controller的监听器
                .setControllerListener(listener)
                .build();

        iv.setController(controller);
    }
先展示一张低分辨率的缩略图,在展开一张高分辨的图
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(pic_umr)
                //先展示一张低分辨率的图片
                .setLowResImageRequest(ImageRequest.fromUri(pic_umr))
                .build();
缩略图预览
仅支持本地uri

Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setLocalThumbnailPreviewsEnabled(true)
    .build();

DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setImageRequest(request)
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);
加载最先可用的图片
但是假设同一张图片有多个 URI 的情况。比如,你可能上传过一张拍摄的照片。原始图片太大而不能上传,所以图片首先经过了压缩。在这种情况下,首先尝试获取本地压缩后的图片 URI,如果失败的话,尝试获取本地原始图片 URI,如果还是失败的话,尝试获取上传到网络的图片 URI。直接下载我们本地可能已经有了的图片不是一件光彩的事。
Image pipeline 会首先从内存中搜寻图片,然后是磁盘缓存,再然后是网络或其他来源。对于多张图片,不是一张一张按上面的过程去做,而是 pipeline 先检查所有图片是否在内存。只有没在内存被搜寻到的才会寻找磁盘缓存。还没有被搜寻到的,才会进行一个外部请求。

Uri uri1, uri2;
ImageRequest request = ImageRequest.fromUri(uri1);
ImageRequest request2 = ImageRequest.fromUri(uri2);
ImageRequest[] requests = { request1, request2 };

DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setFirstAvailableImageRequests(requests)
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);

设置按压状态的图

        GenericDraweeHierarchy hierarchy = builder
                //设置叠加的绘制图,可以是单个,也可以是数组,数组会从第一个开始绘制
//                .setOverlays(overlaysList)
//                .setOverlay()
                //按压状态下展示的图片
               .setPressedStateOverlay(getResources().getDrawable(R.mipmap.ic_launcher))
                .build();

设置gif自动播放

在这一步卡了很久....为啥?
因为没效果啊,连图片都展示不出来
原因不明...

最后,
换了模拟器发现6.0 4.1 的可以 4.4的不行
也有可能是因为我常用4.4的模拟器,安装了很多软件造成的 

更新:
测试完毕,就特么4.4的不行

再次更新:
我用了抓包软件后忘记把ip代理关了
但是比较神奇的是...
普通图片联网就没问题诶
        Uri uri = Uri.parse("http://img.huofar.com/data/jiankangrenwu/shizi.gif");
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                //开启gif效果,如果可以的话
                .setAutoPlayAnimations(true)
                .build();
        iv.setController(controller);
//也可以手动进行控制
ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
    @Override
    public void onFinalImageSet(
        String id,
        @Nullable ImageInfo imageInfo,
        @Nullable Animatable anim) {
        if (anim != null) {
          // 其他控制逻辑
          anim.start();
        }
    }
};

Uri uri;
DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setUri(uri)
    .setControllerListener(controllerListener)
    // 其他设置(如果有的话)
    .build();
mSimpleDraweeView.setController(controller);

获取本地图片的url

    //获取本地图片的url
    public static String getResUrl(Context context, int id) {
        return String.format("res://%s/%d", context.getPackageName(),id);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值