官方介绍

关于 Glide

Glide一个快速高效的Android图片加载库,注重于平滑滚动。Glide提供了易用的API,高性能、可扩展图片解码管道decode pipeline),以及自动资源技术

Glide 支持拉取解码展示视频快照图片,和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入替换自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成工具库。

虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片拉取/缩放/显示的一切需求

性能

Glide 充分考虑了Android图片加载性能的两个关键方面:

为了让用户拥有良好的App使用体验图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面闪烁抖动现象。

Glide使用多个步骤来确保在Android上加载图片可能的快速和平滑


环境配置

Gradle依赖

gradle依赖,目前最新版本为4.12.0

implementation 'com.git`hub.bumptech.glide:glide:4.12.0'`

Glide 支持 Maven 项目依赖方法

<dependency>
<groupId>com.github.bumptech.glide</groupId>
<artifactId>glide</artifactId>
<version>4.12.0</version>
<type>aar</type>
</dependency>

AndroidManifest.xml添加权限设置

项目需求进行添加

    <!-- 网络权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     
    <!-- 读取权限 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     
    <!-- 写入权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

基本用法

Glide 库是使用接口(fluent interface)。对一个完整功能请求,Glide 建造者要求最少有三个参数

//加载图片
Glide.with(context)
    .load(url)
    .into(imageView);

//取消加载
Glide.with(context).clear(imageView);

context可以传入fragmentactivityapplicationContext 等。
load :图片资源可以resourceId 、urluridrawablefile 等。
into :图片会显示对应的 ImageView 中

取消加载并非是必要的操作,在Glide.with()中传入的context如果是activityfragment,当它们的实例销毁时,Glide 会自动取消加载并回收资源

小拓展:
resourceID转换为Uri方法

private static Uri resourceIdToUri(Context context, int resourceId) {
    return Uri.parse("android.resource://" + context.getPackageName()
     + "/" + resourceId);
}

占位符

Glide允许用户指定三种不同类型的占位符,分别在三种不同场景使用他们分别是placeholdererrorfalllback

placeholder(占位符)

占位符是当请求正在执行时被展示的 Drawable 。当请求成功完成时,占位符会被请求到的资源替换。

Glide.with(context)
  .load(url)
  .placeholder(R.drawable.placeholder)
  .into(view);

error错误符)

error Drawable请求永久性失败展示
error()接受的参数只能是已经初始化drawable 对象或者指明它的资源(R.drawable.xxx)

Glide.with(context)
  .load(url)
  .error(R.drawable.error)
  .into(view);

fallback(后备回调符)

fallback Drawable请求的urlnull展示

Glide.with(context)
  .load(url)
  .fallback(R.drawable.fallback)
  .into(view);

当Gilde.load()中传入的资源null,或者是无法成功获取时,展示优先级为fallback > error > placeholder
占位符都是独立的,可以根据开发需要调用。除基本用法中的三个方法,Glide的其他方法也是如此。
占位符是在主线程从Android Resources加载的。占位符应当比较小且容易被系统资源缓存机制缓存起来。

提示多个不同的View上可以使用相同的Drawable,但仅限于无状态drawable例如Bitmap)。但是有状态的 Drawable 不一样,在同一时间多个 View 上展示它们通常不是很安全,因为多个View会立刻修改(mutate) Drawable 。对于有状态的 Drawable ,建议传入一个资源ID,或者使用 newDrawable() 来给每个请求传入一个新的拷贝


选项

请求选项

Glide中的大部分设置项都可以直接应用在 Glide.with() 返回的 RequestBuilder 对象上。

可用的选项包括但不限于:

如果想让应用不同部分之间共享相同的加载选项,可以初始化一个新的 RequestOptions 对象,并在每次加载时通过 apply() 方法传入这个对象

RequestOptions cropOptions = new RequestOptions().centerCrop(context);

Glide.with(context)
    .load(url)
    .apply(cropOptions)
    .into(imageView);

apply() 方法可以调用多次,因此 RequestOption 可以组合使用。如果 RequestOptions 对象之间存在相互冲突设置,那么只有最后一个被应用的 RequestOptions 会生效

过渡选项

TransitionOptions 用于决定加载完成时会发生什么

使用 TransitionOption 可以应用以下变换

  • View淡入
  • 与占位符交叉淡入
  • 或者什么都不发生

如果不使用变换,你图像将会直接出现在其显示位置,替换掉之前的图像。为了避免这种突然的改变,可以淡入view,或者让多个Drawable交叉淡入,而这些都需要使用TransitionOptions完成

例如,要应用一个交叉淡入变换

import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
//import com.bumptech.glide.GenericTransitionOptions.withNoTransition

Glide.with(fragment)
    .load(url)
    .transition(withCrossFade())
//    不发生变换
//    .transition(withNoTransition())
    .into(view);

不同于RequestOptions,TransitionOptions是特定资源类型独有的,假如请求加载一个 Bitmap需要使用 BitmapTransitionOptions ,而不是 DrawableTransitionOptions 。

RequestBuilder

使用 RequestBuilder 可以指定:

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();

或先调用 Glide.with() 然后 load():

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).load(url);
选择资源类型

RequestBuilders 是特定于它们将要加载的资源类型的。默认情况下会得到一个 Drawable RequestBuilder ,但可以使用 as… 方法来改变请求类型。

应用 RequestOptions

前面提到,可以使用 apply() 方法应用 RequestOptions ,使用 transition() 方法应用 TransitionOptions 。

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
  requestBuilder.apply(requestOptions);
  requestBuilder.transition(transitionOptions);
缩略图 (Thumbnail) 请求

Glide 的 thumbnail() API 允许指定一个 RequestBuilder 以与你的主请求并行启动
thumbnail() 会在主请求加载过程展示。如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。thumbnail() API 允许简单快速地加载图像的低分辨率版本,并且同时加载图像的无损版本

Glide.with(context)
  .load(url)
  .thumbnail(Glide.with(context).load(thumbnailUrl))
  .into(imageView);

在只有url而没有thumbnailUrl的情况下,可以使用override方法。

Glide.with(context)
  .load(url)
  .thumbnail(Glide.with(context)
    .load(url)
//    .override(int width, int height)
    .override(int thumbnailSize))
  .into(view);

thumbnail() 方法有一个简化版本,它只需要一个 sizeMultiplier 参数

Glide.with(context)
  .load(url)
  .thumbnail(/*sizeMultiplier=*/ 0.1f)
  .into(imageView);
失败时开始新的请求

error 方法里 来指定一个 RequestBuilder,可以在主请求失败时开始一次新的加载。

Glide.with(context)
  .load(primaryUrl)
  .error(Glide.with(context)
      .load(fallbackUrl))
  .into(imageView);

如果主请求成功完成这个error里的RequestBuilder 将不会被启动。如果你同时指定了一个 thumbnail() 和一个 error() RequestBuilder,则这个后备的 RequestBuilder 将在主请求失败时启动,即使缩略图请求成功也是如此。

请求的优先级

Priority枚举给了四个不同的选项,下面是按照递增priority(优先级)的列表

Priority.LOW
Priority.NORMAL
Priority.HIGH
Priority.IMMEDIATE

优先级并不是完全严格遵守的。Glide 将会用他们作为一个准则,并尽可能处理这些请求,但是它不能保证所有的图片都会按照所要求的顺序加载。

Glide.with(context)
  .load(url)
  .priority(Priority.HIGH)
  .into(imageView);

组件选项

Option 类是给Glide的组件添加参数的通用办法,包括 ModelLoaders , ResourceDecoders , ResourceEncoders , Encoders 等等。一些Glide的内置组件提供了设置项,自定义组件也可以添加设置项。

Option 通过 RequestOptions 类应用到请求上:

Glide.with(context)
  .load(url)
  .option(MyCustomModelLoader.TIMEOUT_MS, 1000L)
  .into(imageView);

变换

在Glide中,Transformations 可以获取资源并修改它,然后返回修改后的资源。通常变换操作是用来完成剪裁或对位图应用过滤器,但它也可以用于转换GIF动画,甚至自定义的资源类型。

内置类型

Glide 提供了很多内置的变换,包括:

  • CenterCrop
  • FitCenter
  • CircleCrop

应用

CenterCrop

CenterCrop()是一个裁剪技术,即缩放图像让它填充到 ImageView 界限内并且裁剪额外部分。ImageView 可能会完全填充,但图像可能不会完整显示

Glide.with(context)
  .load(url)
  .centerCrop()
  .into(imageView)

或使用 RequestOptions

RequestOptions options = new RequestOptions();
options.centerCrop();

Glide.with(context)
    .load(url)
    .apply(options)
    .into(imageView);
FitCenter

fitCenter() ,即缩放图像让图像都测量出来等于或小于 ImageView 的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView。

Glide.with(context)
  .load(url)
  .fitCenter()
  .into(imageView)
CircleCrop

CircleCrop()和fitCenter()行为类型,但会剪裁出圆形图片。

Glide.with(context)
  .load(url)
  .circleCrop()
  .into(imageView)

Transformations

添加依赖

compile 'jp.wasabeef:glide-transformations:4.0.0'
//使用GPU转换
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:xxxx'

多重变换

默认情况下,每个 transform() 调用,或任何特定转换方法的调用都会替换掉之前的变换。

如果想在单次加载中应用多个变换,请使用 MultiTransformation 类,或其快捷方法 .transforms() 。

Glide.with(context)
  .load(url)
//   MultiTransformation 类
//  .transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation())

// 快捷方法
  .transform(new FitCenter(), new YourCustomTransformation())
  .into(imageView);

向 MultiTransformation 的构造器传入变换参数的顺序,决定了这些变换的应用顺序

自定义变换

一个简单的BitmapTransformation

如果只需要变换 Bitmap,最好是从继承 BitmapTransformation 开始。BitmapTransformation 为我们处理了一些基础的东西,例如,如果变换返回了一个新修改的 Bitmap ,BitmapTransformation将负责提取回收原始的 Bitmap。

public class FillSpace extends BitmapTransformation {
    private static final String ID = "com.bumptech.glide.transformations.FillSpace";
    private static final String ID_BYTES = ID.getBytes(STRING_CHARSET_NAME);

    @Override
    public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        if (toTransform.getWidth() == outWidth &amp;&amp; toTransform.getHeight() == outHeight) {
            return toTransform;
        }

        return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, /*filter=*/ true);
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest)
        throws UnsupportedEncodingException {
      messageDigest.update(ID_BYTES);
    }
    
    @Override
    public void equals(Object o) {
      return o instanceof FillSpace;
    }

    @Override
    public int hashCode() {
      return ID.hashCode();
    } 
}
使用这个BitmapTransformation

Glide 有两种方式去使用转换。首先是传一个类的实例作为参数给 .transform()。这里可以使用任何转换,无论它是否是用于图像还是 Gif。其他选择是使用 .bitmapTransform(),它只能用于 bitmap 的转换。因为我们上面的实现是为 bitmap 设计的,这两者我们都可以用:

Glide  
    .with(context)
    .load(url)
    .transform(new FillSpace())
    //.bitmapTransform(new FillSpace()) // this would work too!
    .into( imageView );
注意

请特别注意,对于任何 Transformation 子类,包括 BitmapTransformation,有三个方法 必须 实现它们,以使得磁盘内存缓存正确工作。如果没有复写equals()和hashCode(),BitmapTransformation 和 Transformation 也能通过编译,但这并不意味着它们能正常工作。

ImageView的自动变换

在Glide中,当一个 ImageView 开始加载时,Glide可能会自动应用 FitCenter 或 CenterCrop ,这取决于view的 ScaleType 。如果 scaleType 是 CENTER_CROP , Glide 将会自动应用 CenterCrop 变换。如果 scaleType 为 FIT_CENTER 或 CENTER_INSIDE ,Glide会自动使用 FitCenter 变换。

我们可以覆写默认的变换,只需要一个带有 Transformation 集合的 RequestOptions 即可。另外也可以通过使用 dontTransform() 确保不会自动应用任何变换。


目标

关于Target

在Glide中,Target 是介于请求和请求者之间中介者的角色。Target 负责展示占位符,加载资源,并为每个请求决定合适的尺寸。被使用得最频繁的是 ImageViewTargets ,它用于在 ImageView 上展示占位符、Drawable 和 Bitmap 。

指定目标

into(Target) 方法不仅仅用于启动每个请求,它同时也指定了接收请求结果的 Target:

Target<Drawable> target = 
  Glide.with(context)
    .load(url)
    .into(new Target<Drawable>() {
      ...
    });

Glide 提供了一个辅助方法 into(ImageView) ,它接受一个 ImageView 参数并为其请求的资源类型包装了一个合适的 ImageViewTarget:

Target<Drawable> target = 
  Glide.with(context)
    .load(url)
    .into(imageView);

取消和重用

into(Target) 和 into(ImageView) 都返回了一个 Target 实例。重用这个 Target 来在将来开始一个新的加载,之前开始的任何请求都会被取消,它们使用的资源将被释放。
也可以使用返回的 Target 来 clear() 之前的加载,这将在不需要开始新的加载的情况下释放掉相关资源。

Target<Drawable> target = 
  Glide.with(fragment)
    .load(url)
    .into(new Target<Drawable>() {
      ...
    });
... 
// Some time in the future:
Glide.with(context)
  .load(newUrl)
  .into(target);
  
// Some time in the future:
Glide.with(context).clear(target);

//与加载到imageView类似
Glide.with(context)
  .load(newUrl)
  .into(imageView);
Glide.with(context).clear(imageView);

SimpleTarget

指定尺寸
SimpleTarget target = new SimpleTarget<Bitmap>( 250, 250 ) {  
    @Override
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
        imageView.setImageBitmap( bitmap );
    }
};

 Glide.with( context.getApplicationContext() ) // safer!
      .load( url )
      .asBitmap()
      .into( target );

动画资源
Glide.with(context)
  .load(url)
  .into(new SimpleTarget<>() {
    @Override
    public void onResourceReady(Drawable resource, Transition<GifDrawable> transition) {
      if (resource instanceof Animatable) {
        resource.start();
      }
      // Set the resource wherever you need to use it.
    }
  });

ViewTarget

Glide 并不支持加载图片到自定义 view 中,所以可以使用ViewTarget 来实现

     CustomView customView = (CustomView) findViewById( R.id.custom_view );

    viewTarget = new ViewTarget<CustomView, GlideDrawable>( customView ) {
        @Override
        public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            //view.setImag是自定义view里自己去实现的方法
            this.view.setImage( resource.getCurrent() );
        }
    };

    Glide
        .with( context) 
        .load( url )
        .into( viewTarget );

Target下载图片文件

val future: FutureTarget<File> = Glide.with(context)
                .load(url)
                .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
val cacheFile: File = future.get()

清理

当你完成了对资源的使用时,需要及时清理创建的这些 Target 。即使请求已经完成了,也应该使用 clear() 以使 Glide 可以重用被这次加载使用的资源 (特别是 Bitmap )。未调用 clear() 会浪费 CPU 和内存阻塞更重要的加载,甚至如果你在同一个 surface (View, Notification, RPC 等) 上有两个 Target,可能会引发图片显示错误。对于像 SimpleTarget这种无法从一个新实例跟踪前一个请求的 Target 来说,及时清理尤为重要。


缓存

默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级缓存

1.活动资源 (Active Resources) – 现在是否有另一个 View 正在展示这张图片
2.内存缓存 (Memory cache) – 该图片是否最近被加载过并仍存在于内存中
3.资源类型(Resource) – 该图片是否之前曾被解码、转换并写入磁盘缓存
4.数据来源 (Data) – 构建这个图片的资源是否之前曾被写入文件缓存

前两步检查图片是否在内存中,如果是则直接返回图片。
后两步则检查图片是否在磁盘上,以便快速但异步返回图片。

如果四个步骤都未能找到图片,则Glide会返回到原始资源以取回数据(原始文件,Uri, Url等)。

磁盘缓存策略

DiskCacheStrategy 可被 diskCacheStrategy 方法应用到每一个单独的请求。

DiskCacheStrategy.NONE ————-什么都不缓存
DiskCacheStrategy.DATA ————- 仅仅只缓存原来的全分辨率的图像。
DiskCacheStrategy.RESOURCE —–仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
DiskCacheStrategy.ALL —————-缓存所有版本的图像
DiskCacheStrategy.AUTOMATIC —-让Glide根据图片资源智能选择使用哪一种缓存策略默认选项

跳过磁盘缓存

Glide.with(context)
  .load(url)
  .diskCacheStrategy(DiskCacheStrategy.NONE)
  .into(view);

跳过内存缓存

Glide.with(context)
  .load(url)
  .skipMemoryCache(true)
  .into(view);

仅从缓存加载图片

省流模式下可以使用此方法

Glide.with(context)
  .load(url)
  .onlyRetrieveFromCache(true)
  .into(imageView);

清理缓存

Glide.get(context).clearDiskCache();//只能在子线程执行
Glide.get(context).clearMemory();//只能在主线程执行

调试

打开日志

Glide 的 GeneralRequest 类提供了一个方法去设置 log级别。需要用shell命令打开

adb shell setprop log.tag.GenericRequest DEBUG  

RequestListener

Glide.with(fragment)
   .load(url)
   .listener(new RequestListener() {
       @Override
       boolean onLoadFailed(@Nullable GlideException e, Object model,
           Target<R> target, boolean isFirstResource) {
           
         Log.e(TAG, "Load failed", e);

         return false; // Allow calling onLoadFailed on the Target.
       }

       @Override
       boolean onResourceReady(R resource, Object model, Target<R> target,
           DataSource dataSource, boolean isFirstResource) {
           
         return false; // Allow calling onResourceReady on the Target.
         
       }
    })
//    .error(R.drawable.error)
    .into(imageView);

Module

Glide module 是一个抽象方法,全局改变 Glide 行为的一个方式
自定义Module可以实现定制缓存大小、图片池大小以及改变解码规则等等功能属于Glide的高阶使用技巧本文不作展开

参考资料
Glide官方文档https://muyangmin.github.io/glide-docs-cn/
Glide系列博客https://mrfu.me/2016/02/27/Glide_Getting_Started/ 作者:Yuan Fu

原文地址:https://blog.csdn.net/weixin_49078536/article/details/126787387

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_37702.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注