Glide常规用法

转自 http://www.cnblogs.com/whoislcj/p/5558168.html

Android图片缓存之初识Glide

前言:

     前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架。技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实现方案不能满足项目的需求改用Afinal,由于Afinal不再维护而选择了师出同门的Xutils,中间也接触过别的开源框架比如Picasso,对Picasso的第一次印象就不太好,初次接触是拿到了公司刚从外包公司接手过来的图片社交类app,对内存占用太大,直接感受就是导致ListView滑动有那么一点卡顿,老牌的图片缓存框架universalImageLoader听说过一直没有真正使用过,之前项目都很小,差不多几百万级别的app,一直使用的都是Xutils,最近觉得项目大起来了,万一Xutils不维护了或者说要求支持的图片格式多起来的时候,可能Xutils就不是最佳选择了,这也是来学习Gilde的根本动机吧。其实本来想着去学习Facebook的Fresco图片框架,但是简单的看了一下,需要连同自定义控件一起使用,功能虽然强大,但是对于已经在维护的项目修改成本那可不是一般的高,以后有兴趣在学习吧!

 图片缓存相关博客地址:

Glide简介:

        Glide 是 Google 员工的开源项目, Google I/O 上被推荐使用,一个高效、开源、Android设备上的媒体管理框架,它遵循BSD、MIT以及Apache 2.0协议发布。Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。创建Glide的主要目的有两个,一个是实现平滑的图片列表滚动效果,另一个是支持远程图片的获取、大小调整和展示。

 gitHub地址:https://github.com/bumptech/glide

Glide特点

  •  使用简单
  • 可配置度高,自适应程度高
  • 支持常见图片格式 Jpg png gif webp
  • 支持多种数据源  网络、本地、资源、Assets 等
  • 高效缓存策略    支持Memory和Disk图片缓存 默认Bitmap格式采用RGB_565内存使用至少减少一半
  • 生命周期集成   根据Activity/Fragment生命周期自动管理请求
  • 高效处理Bitmap  使用Bitmap Pool使Bitmap复用,主动调用recycle回收需要回收的Bitmap,减小系统回收压力

Glide简单使用

1.)添加引用 build.gradle 中添加配置
  compile 'com.github.bumptech.glide:glide:3.7.0'
2.)设置绑定生命周期

我们可以更加高效的使用Glide提供的方式进行绑定,这样可以更好的让加载图片的请求的生命周期动态管理起来

  Glide.with(Context context);// 绑定Context
  Glide.with(Activity activity);// 绑定Activity
  Glide.with(FragmentActivity activity);// 绑定FragmentActivity
  Glide.with(Fragment fragment);// 绑定Fragment

 

3. )简单的加载图片实例
 Glide.with(this).load(imageUrl).into(imageView);
4.)设置加载中以及加载失败图片

api里面对placeholder()、error()函数中有多态实现 用的时候可以具体的熟悉一下

Glide.with(this).load(imageUrl).placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher).into(imageView);
5.)设置跳过内存缓存
 Glide.with(this).load(imageUrl).skipMemoryCache(true).into(imageView);
6.)设置下载优先级
Glide.with(this).load(imageUrl).priority(Priority.NORMAL).into(imageView);
7.)设置缓存策略
Glide.with(this).load(imageUrl).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);

策略解说:

all:缓存源资源和转换后的资源

none:不作任何磁盘缓存

source:缓存源资源

result:缓存转换后的资源

8.)设置加载动画

api也提供了几个常用的动画:比如crossFade()

  Glide.with(this).load(imageUrl).animate(R.anim.item_alpha_in).into(imageView);
R.anim.item_alpha_in
复制代码
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:duration="500"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>
</set>
复制代码
9.)设置缩略图支持

这样会先加载缩略图 然后在加载全图

 Glide.with(this).load(imageUrl).thumbnail(0.1f).into(imageView);
10.)设置加载尺寸
 Glide.with(this).load(imageUrl).override(800, 800).into(imageView);
11.)设置动态转换
 Glide.with(this).load(imageUrl).centerCrop().into(imageView);

    api提供了比如:centerCrop()、fitCenter()等函数也可以通过自定义Transformation,举例说明:比如一个人圆角转化器

复制代码
 public class GlideRoundTransform extends BitmapTransformation {
        private float radius = 0f;
        public GlideRoundTransform(Context context) {
            this(context, 4);
        }

        public GlideRoundTransform(Context context, int dp) {
            super(context);
            this.radius = Resources.getSystem().getDisplayMetrics().density * dp;
        }

        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            return roundCrop(pool, toTransform);
        }

        private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
            if (source == null) return null;

            Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            if (result == null) {
                result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            }
            Canvas canvas = new Canvas(result);
            Paint paint = new Paint();
            paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
            paint.setAntiAlias(true);
            RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
            canvas.drawRoundRect(rectF, radius, radius, paint);
            return result;
        }

        @Override
        public String getId() {
            return getClass().getName() + Math.round(radius);
        }
    }
复制代码

 

具体使用

Glide.with(this).load(imageUrl).transform(new GlideRoundTransform(this)).into(imageView);
12.)设置要加载的内容

项目中有很多需要先下载图片然后再做一些合成的功能,比如项目中出现的图文混排,该如何实现目标下

复制代码
        Glide.with(this).load(imageUrl).centerCrop().into(new SimpleTarget<GlideDrawable>() {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                imageView.setImageDrawable(resource);
            }
        });
复制代码
13 .)设置监听请求接口
复制代码
  Glide.with(this).load(imageUrl).listener(new RequestListener<String, GlideDrawable>() {
            @Override
            public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                //imageView.setImageDrawable(resource);
                return false;
            }
        }).into(imageView);
复制代码

 

设置监听的用处 可以用于监控请求发生错误来源,以及图片来源 是内存还是磁盘

15.)设置动态GIF加载方式
 Glide.with(this).load(imageUrl).asBitmap().into(imageView);//显示gif静态图片
 Glide.with(this).load(imageUrl).asGif().into(imageView);//显示gif动态图片
 16.)缓存的动态清理
 Glide.get(this).clearDiskCache();//清理磁盘缓存 需要在子线程中执行
 Glide.get(this).clearMemory();//清理内存缓存  可以在UI主线程中进行
<think>好的,用户之前询问过关于ImageView不显示的问题,现在他问的是如何用Glide显示图片还原手机浏览图片的大小。我需要先理解他的具体需求。他可能是在应用中显示图片时,图片的大小不合适,要么被拉伸,要么被裁剪,或者没有保持原图的比例,导致用户无法像在手机相册里那样查看完整的原始尺寸图片。 首先,我需要回顾Glide的scaleType设置以及相关的调整方法。Glide默认可能会根据ImageView的尺寸来调整图片,但用户希望图片显示的实际大小和原图一致,可能需要调整缩放类型或ImageView的布局参数。 接下来,用户提到的“手机浏览图片的大小”可能指的是像系统相册应用那样,图片可以完整显示,支持手势缩放和平移。所以可能需要结合ImageView的scaleType和手势库来实现。 然后,考虑到用户之前的代码中使用了centerCrop,这可能导致图片被裁剪。而用户现在希望不裁剪,而是完整显示,可能需要使用fitCenter或其他scaleType。另外,ImageView的layout_width和layout_height设置为wrap_content可能无法正确显示大图,可能需要动态调整尺寸,或者使用自定义的Target来获取图片的实际尺寸并设置给ImageView。 还需要考虑大图的内存问题,Glide如何优化加载,防止OOM。同时,如果用户需要手势操作,可能需要集成像PhotoView这样的库来实现缩放和拖动。 可能还需要检查是否有其他布局参数限制了ImageView的大小,比如父容器的约束,或者权重设置不正确,导致图片无法展开到实际尺寸。 最后,总结几种可能的解决方案,分步骤说明如何调整scaleType,动态设置ImageView尺寸,使用自定义Target,以及集成手势库,并提供代码示例和注意事项,比如内存管理和布局约束。</think>--- ### 一、核心原理:Glide显示原始尺寸的关键 要让Glide显示的图片尺寸与手机相册中完全一致,需同时满足以下 **3个条件**: 1. **不压缩图片**:禁用默认的`Downsampling` 2. **精确尺寸适配**:获取图片原始尺寸动态设置ImageView 3. **正确缩放模式**:使用`ScaleType.FIT_CENTER`或自定义手势控制 --- ### 二、完整实现步骤(分优先级) #### 1. 基础方案:保持原始比例 **适用场景**:快速实现近似相册的展示效果 ```kotlin Glide.with(context) .load(imageUri) .override(Target.SIZE_ORIGINAL) // 关键参数 .fitCenter() // 保持比例居中显示 .into(imageView) ``` **XML布局调整**: ```xml <ImageView android:layout_width="match_parent" // 宽度填满容器 android:layout_height="wrap_content" // 高度按比例自适应 android:scaleType="fitCenter" // 必须与代码一致 android:adjustViewBounds="true"/> // 允许视图边界自适应 ``` --- #### 2. 精准方案:动态获取原始尺寸 **适用场景**:需要精确像素级还原 ```kotlin Glide.with(context) .asBitmap() .load(imageUri) .addListener(object : RequestListener<Bitmap> { override fun onResourceReady( resource: Bitmap, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean ): Boolean { // 动态设置ImageView尺寸 imageView.layoutParams = FrameLayout.LayoutParams( resource.width, // 原始宽度 resource.height // 原始高度 ).apply { gravity = Gravity.CENTER } imageView.setImageBitmap(resource) return true } // ...省略错误处理 }) .submit() ``` --- #### 3. 高级方案:集成手势缩放 **推荐库**:使用[PhotoView](https://github.com/Baseflow/PhotoView)实现相册级体验 ```groovy // build.gradle implementation 'com.github.chrisbanes:PhotoView:2.3.0' ``` **实现代码**: ```xml <com.github.chrisbanes.photoview.PhotoView android:id="@+id/photo_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitCenter"/> ``` ```kotlin Glide.with(this) .load(imageUri) .override(Target.SIZE_ORIGINAL) .into(photo_view).apply { // 启用手势控制 photo_view.setMaximumScale(10f) // 最大缩放倍数 photo_view.setMediumScale(5f) photo_view.setScaleLevels(1f, 5f, 10f) } ``` --- ### 三、关键参数对比表 | 配置参数 | 效果差异 | 内存消耗 | 适用场景 | |---------|---------|---------|---------| | `override(500)` | 强制指定尺寸 | 低 | 缩略图展示 | | `override(SIZE_ORIGINAL)` | 显示原始尺寸 | 高 | 高清大图查看 | | `diskCacheStrategy(DATA)` | 缓存原始数据 | 高 | 需要重复加载原图 | | `diskCacheStrategy(RESOURCE)` | 缓存处理后的图片 | 低 | 常规使用 | --- ### 四、内存优化技巧 1. **大图警告**:当图片尺寸超过屏幕分辨率2倍时需压缩 ```kotlin val displayMetrics = resources.displayMetrics val maxWidth = displayMetrics.widthPixels * 2 val maxHeight = displayMetrics.heightPixels * 2 Glide.with(this) .load(imageUri) .override(maxWidth, maxHeight) // 智能压缩 .into(imageView) ``` 2. **生命周期绑定**:防止内存泄漏 ```kotlin Glide.with(viewLifecycleOwner) // 在Fragment中使用 .load(imageUri) .into(imageView) ``` --- ### 五、常见问题排查 1. **图片显示不全** - ✅ 检查父容器的`clipChildren`属性是否设为`false` - ✅ 确认XML布局中无`android:maxWidth`限制 2. **OOM崩溃处理** ```kotlin // 在Application中配置 Glide.init(context, GlideBuilder().apply { setDefaultRequestOptions( RequestOptions() .format(DecodeFormat.PREFER_RGB_565) // 减少内存占用 ) }) ``` --- ### 六、最终推荐方案 ```kotlin // 最佳实践组合方案 fun loadFullSizeImage(context: Context, uri: Uri, imageView: ImageView) { val displayMetrics = context.resources.displayMetrics Glide.with(context) .load(uri) .signature(ObjectKey(System.currentTimeMillis())) // 防止缓存问题 .override(Target.SIZE_ORIGINAL) .addListener(object : RequestListener<Drawable> { override fun onResourceReady(...): Boolean { (imageView.parent as? ViewGroup)?.clipChildren = false return false } }) .apply { if (imageView is PhotoView) { into(imageView.apply { setScaleLevels(1f, 3f, 5f) setMaximumScale(8f) }) } else { into(imageView) } } } ``` 通过上述方案,可以实现与系统相册完全一致的图片显示效果。若需要更精细的控制,建议结合`SubsamplingScaleImageView`实现深度缩放功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值