美文网首页
Glide多种组合使用方式

Glide多种组合使用方式

作者: lc951 | 来源:发表于2022-01-04 16:59 被阅读0次
    glide.png

    官方使用建议:

    // For a simple view:
    @Override 
    public void onCreate(Bundle savedInstanceState) {
      ...
      ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
    
      Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
    }
    
    // For a simple image list:
    @Override 
    public View getView(int position, View recycled, ViewGroup container) {
      final ImageView myImageView;
      if (recycled == null) {
        myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
      } else {
        myImageView = (ImageView) recycled;
      }
    
      String url = myUrls.get(position);
    
      Glide
        .with(myFragment)
        .load(url)
        .centerCrop()
        .placeholder(R.drawable.loading_spinner)
        .into(myImageView);
      return myImageView;
    }
    

    官方指导RecyclerView使用时加载图片

    有时在使用 RecyclerView时,View 可能被重用且保持了前一个位置的尺寸,但在当前位置会发生改变。为了处理这种场景,你可以创建一个新的 ViewTarget 并为 waitForLayout() 方法传入 true:

    @Override
    public void onBindViewHolder(VH holder, int position) {
      Glide.with(fragment)
        .load(urls.get(position))
        .into(new DrawableImageViewTarget(holder.imageView, /*waitForLayout=*/ true));
    

    优化性能指导

    清理

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

    Glide.with(fragment)
      .load(url)
      .into(imageView);
    
    // Some time in the future:
    Glide.with(fragment).clear(imageView);
    

    动画资源和定制目标

    Glide.with(fragment)
      .asGif()
      .load(url)
      .into(new SimpleTarget<>() {
        @Override
        public void onResourceReady(GifDrawable resource, Transition<GifDrawable> transition) {
          resource.start();
          // Set the resource wherever you need to use it.
        }
      });
    

    如果你加载的是 Bitmap 或 GifDrawable,你可以判断这个可绘制对象是否实现了 Animatable:

    Glide.with(fragment)
      .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.
        }
      });
    

    注意

    Android中的动画代价是比较大的,尤其是同时开始大量动画的时候。 交叉淡入和其他涉及 alpha 变化的动画显得尤其昂贵。 此外,动画通常比图片解码本身还要耗时。在列表和网格中滥用动画可能会让图像的加载显得缓慢而卡顿。为了提升性能,请在使用 Glide 向 ListView , GridView, 或 RecyclerView 加载图片时考虑避免使用动画,尤其是大多数情况下,你希望图片被尽快缓存和加载的时候。作为替代方案,请考虑预加载,这样当用户滑动到具体的 item 的时候,图片已经在内存中了。

    对占位符和透明图片交叉淡入【官方提醒】

    虽然禁用交叉淡入通常是一个比较好的默认行为,当待加载的图片包含透明像素时仍然可能造成问题。当占位符比实际加载的图片要大,或者图片部分为透明时,禁用交叉淡入会导致动画完成后占位符在图片后面仍然可见。如果你在加载透明图片时使用了占位符,你可以启用交叉淡入,具体办法是调整 DrawableCrossFadeFactory 里的参数并将结果传到 transition() 中:

    DrawableCrossFadeFactory factory =
            new DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true).build();
    
    GlideApp.with(context)
            .load(url)
            .transition(withCrossFade(factory))
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .placeholder(R.color.placeholder)
            .into(imageView);
    

    以前屏幕比较小,列表图片和一些图片加载展现的尺寸不大,所以就算有图片叠加问题不留意也看不出来。
    但是最近的网络电视流行。图片加载尺寸越来越大这个问题就有可能比较严重了。尤其进行TV开发者留意

    应用程序(Applications)和程序库 (Libraries)使用建议

    应用程序(Applications)如果希望使用集成库和/或 Glide 的 API 扩展,则需要:

    恰当地添加一个 AppGlideModule 实现。
    (可选)添加一个或多个 LibraryGlideModule 实现。
    给上述两种实现添加 @GlideModule 注解。
    添加对 Glide 的注解解析器的依赖。
    在 proguard 中,添加对 AppGlideModules 的 keep 。

    @GlideModule
    public class FlickrGlideModule extends AppGlideModule {
      @Override
      public void registerComponents(Context context, Registry registry) {
        registry.append(Photo.class, InputStream.class, new FlickrModelLoader.Factory());
      }
    }
    

    程序库如果需要注册定制组件,例如 ModelLoader,可按以下步骤执行:

    添加一个或多个 LibraryGlideModule 实现,以注册新的组件。
    为每个 LibraryGlideModule 实现,添加 @GlideModule 注解。
    添加 Glide 的注解处理器的依赖。
    一个 [LibraryGlideModule] 的例子,在 Glide 的OkHttp 集成库 中:

    @GlideModule
    public final class OkHttpLibraryGlideModule extends LibraryGlideModule {
      @Override
      public void registerComponents(Context context, Glide glide, Registry registry) {
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
      }
    }
    

    避免在程序库中使用 AppGlideModule

    程序库一定 不要 包含 AppGlideModule 实现。这么做将会阻止依赖该库的任何应用程序管理它们的依赖,或配置诸如 Glide 缓存大小和位置之类的选项。

    此外,如果两个程序库都包含 AppGlideModule,应用程序将无法在同时依赖两个库的情况下通过编译,而不得不在二者之中做出取舍。

    这确实意味着程序库将无法使用 Glide 的 generated API,但是使标准的 RequestBuilder 和 RequestOptions 加载仍然有效(可以在 选项 页找到例子)

    冲突

    应用程序可能依赖多个程序库,而它们每一个都可能包含一个或更多的 LibraryGlideModules 。在极端情况下,这些 LibraryGlideModules 可能定义了相互冲突的选项,或者包含了应用程序希望避免的行为。应用程序可以通过给他们的 AppGlideModule 添加一个 @Excludes 注解来解决这种冲突,或避免不需要的依赖。

    例如,如果你依赖了一个库,它有一个 LibraryGlideModule 叫做com.example.unwanted.GlideModule,而你不想要它:

    @Excludes(com.example.unwanted.GlideModule)
    @GlideModule
    public final class MyAppGlideModule extends AppGlideModule { }
    

    你也可以排除多个模块:

    @Excludes({com.example.unwanted.GlideModule, com.example.conflicing.GlideModule})
    @GlideModule
    public final class MyAppGlideModule extends AppGlideModule { }
    

    @Excludes 注解不仅可用于排除 LibraryGlideModules 。如果你还在从 Glide v3
    到新版本的迁移过程中,你还可以用它来排除旧的,废弃的 GlideModule 实现

    【省流量模式】仅从缓存加载图片

    某些情形下,你可能希望只要图片不在缓存中则加载直接失败(比如省流量模式)。如果要完成这个目标,你可以在单个请求的基础上使用 onlyRetrieveFromCache 方法:

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

    如果图片在内存缓存或在磁盘缓存中,它会被展示出来。否则只要这个选项被设置为 true ,这次加载会视同失败。

    【图片验证码】跳过缓存

    如果你想确保一个特定的请求跳过磁盘和/或内存缓存(比如,图片验证码 ),Glide 也提供了一些替代方案。

    仅跳过内存缓存,请使用 skipMemoryCache() :

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

    仅跳过磁盘缓存,请使用 DiskCacheStrategy.NONE :

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

    这两个选项可以同时使用:

    Glide.with(fragment)
      .load(url)
      .diskCacheStrategy(DiskCacheStrategy.NONE)
      .skipMemoryCache(true)
      .into(view);
    

    从源码解析的时候发现的使用方式粗略有25种组合

    * @see Glide#with(android.app.Activity)
     * @see Glide#with(androidx.fragment.app.FragmentActivity)
     * @see Glide#with(android.app.Fragment)
     * @see Glide#with(androidx.fragment.app.Fragment)
     * @see Glide#with(Context)
     * 
    

    //源码使用方式一

    
    FutureTarget<Bitmap> target =
            Glide.with(app)
                .asBitmap()
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .skipMemoryCache(true)
                .override(targetSize)
                .load(resourceId)
                .listener(
                    new RequestListener<Bitmap>() {
                      @Override
                      public boolean onLoadFailed(
                          @Nullable GlideException e,
                          Object model,
                          Target<Bitmap> target,
                          boolean isFirstResource) {
                        return false;
                      }
    
                      
    
    @Override
                      public boolean onResourceReady(
                          Bitmap resource,
                          Object model,
                          Target<Bitmap> target,
                          DataSource dataSource,
                          boolean isFirstResource) {
                        dataSourceRef.set(dataSource);
                        return false;
                      }
                    })
                .submit();
                ....
        Glide.with(app).clear(target);
    
    

    //用法二

     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), ResourceIds.raw.canonical);
        byte[] data = concurrency.get(Glide.with(context).as(byte[].class).load(bitmap).submit());
     
    

    //三

     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), ResourceIds.raw.canonical);
        byte[] data =
            concurrency.get(
                Glide.with(context)
                    .as(byte[].class)
                    .load(new BitmapDrawable(context.getResources(), bitmap))
                    .submit());
    

    //4

    byte[] data =concurrency.get(Glide.with(context).as(byte[].class).load(ResourceIds.raw.video).submit());
    

    //5

    Glide.with(context).as(byte[].class).load(writeVideoToFile()).submit()
    
    

    //6

    byte[] data =
            concurrency.get(
                Glide.with(context)
                    .as(byte[].class)
                    .load(writeVideoToFile().getAbsolutePath())
                    .submit());
    

    //7

     byte[] data =
            concurrency.get(
    Glide.with(context).as(byte[].class).load(Uri.fromFile(writeVideoToFile())).submit());
    

    //8

    Glide.with((Context) ApplicationProvider.getApplicationContext()).clear(imageView);
    

    //9

     Bitmap bitmap =
            concurrency.get(
    Glide.with(context).asBitmap().load(getDataUriString(CompressFormat.JPEG)).submit());
     Bitmap bitmap =
            concurrency.get(
                Glide.with(context).asBitmap().load(getDataUriString(CompressFormat.PNG)).submit());
    Bitmap bitmap =
            concurrency.get(
                Glide.with(context).asBitmap().load(getDataUri(CompressFormat.JPEG)).submit());
                ...
                private Uri getDataUri(CompressFormat format) {
        return Uri.parse(getDataUriString(format));
      }
                private String getDataUriString(CompressFormat format) {
        String bytes = getBase64BitmapBytes(format);
        String imageType;
        switch (format) {
          case PNG:
            imageType = "png";
            break;
          case JPEG:
            imageType = "jpeg";
            break;
          case WEBP:
            imageType = "webp";
            break;
          default:
            throw new IllegalArgumentException("Unrecognized format: " + format);
        }
    
        String mimeType = "image/" + imageType;
        return "data:" + mimeType + ";base64," + bytes;
      }
      ...
      private String getBase64BitmapBytes(CompressFormat format) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Drawable drawable =
            Preconditions.checkNotNull(ContextCompat.getDrawable(context, ResourceIds.raw.canonical));
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        bitmap.compress(format, 100, bos);
        byte[] data = bos.toByteArray();
        return Base64.encodeToString(data, /*flags=*/ 0);
      }
    
    

    //10

    Drawable colorDrawable = new ColorDrawable(Color.RED);
        Drawable result =
            Glide.with(context)
                .load(colorDrawable)
                .apply(new RequestOptions().optionalCenterCrop())
                .submit()
                .get();
     =====================
    Drawable result =
            Glide.with(context)
                .load(colorDrawable)
                .apply(new RequestOptions().centerCrop())
                .submit(100, 100)
                .get(); 
    

    //11

    Glide.with(context).load(ResourceIds.raw.canonical).listener(requestListener).submit()
    

    //12

    Drawable drawable = concurrency.get(Glide.with(context).load(raw.canonical).submit());
      
    

    //13

    Glide.with(app)
              .load(loadStep.getModel(beforeData))
              .diskCacheStrategy(DiskCacheStrategy.NONE)
              .override(Target.SIZE_ORIGINAL)
              .submit()
              .get(15, TimeUnit.SECONDS);
    

    //14

    Glide.with(app)
                    .as(Baz.class)
                    .load(model)
                    .skipMemoryCache(true)
                    .diskCacheStrategy(DiskCacheStrategy.NONE)); 
    

    //15

    Glide.with(getContext()).asDrawable().load(android.R.drawable.ic_menu_rotate).into(this);
    

    //16

    byte[] data = getLargeImageBytes();
        Bitmap bitmap = concurrency.get(Glide.with(context).asBitmap().load(data).submit());
    
    

    //17

    ByteBuffer buffer = ByteBuffer.wrap(getLargeImageBytes());
        Bitmap bitmap = concurrency.get(Glide.with(context).asBitmap().load(buffer).submit()); 
    
    

    //18

    Glide.with(context).load(canonicalBytes).apply(skipMemoryCacheOf(false))
    

    //19

    Glide.with(context).asDrawable().load(canonicalBytes).apply(skipMemoryCacheOf(false)
    

    //20

    Drawable frame = concurrency.get(Glide.with(context).load(ResourceIds.raw.video).submit());
    

    //21

    Drawable frame =
            concurrency.get(Glide.with(context).load(new Integer(ResourceIds.raw.video)).submit());
    
    

    //22

    Bitmap frame =
            concurrency.get(Glide.with(context).asBitmap().load(ResourceIds.raw.video).submit());
    

    //23

    Drawable drawable =
            Glide.with(context)
                .load(android.R.drawable.star_big_off)
                .apply(centerCropTransform())
                .submit()
                .get();
    

    //24

    Drawable drawable =
            Glide.with(context)
                .load(ResourceIds.drawable.shape_drawable)
                .apply(bitmapTransform(new RoundedCorners(10)))
                .submit(100, 200)
                .get();
    
    
    
    Bitmap bitmap =
            Glide.with(context)
                .asBitmap()
                .load(ResourceIds.drawable.shape_drawable)
                .submit(100, 200)
                .get();
    
    Bitmap bitmap =
            Glide.with(context)
                .asBitmap()
                .load(ResourceIds.drawable.shape_drawable)
                .apply(centerCropTransform())
                .submit(100, 200)
                .get();
    

    //25

    
    Bitmap bitmap = Glide.with(context).asBitmap().load(uri).submit().get();
    
    Bitmap bitmap =        Glide.with(context).asBitmap().apply(centerCropTransform()).load(uri).submit().get();
    
    Drawable drawable = Glide.with(context).load(uri).submit().get();
    

    丰富的gilde使用方式,总有一款适合你

    总结

    • 使用上非常简洁 glide陪伴着android系统一起成长。
    • 其中的设计理念和设计实践都很值得App开发者学习和借鉴
    • 后期将从设计模式、算法、测试的几个角度深度解析Glide源码工程。
    • 如果发现很好的实践将会单独摘出来说明使用环境和条件

    更多设计模式解读

    单例模式
    Glide设计模式之单例模式
    空对象模式
    Glide设计模式之空对象模式【EmptyModelLoader】【EmptyList<E>
    建造者模式
    Glide多种组合使用方式记录--没有全部亲测,大家可以根据实际需要选用
    Glide设计模式之建造者(builder)模式1【GlideBuilder】
    Glide设计模式之建造者(builder)模式2【RequestBuilder】
    Glide设计模式之建造者(builder)模式3【RequestOptions】【BaseRequestOptions】
    Glide设计模式之建造者(builder)模式4总结【MemorySizeCalculator】【GlideExecutor】【PreFillType】【LazyHeaders】

    相关文章

      网友评论

          本文标题:Glide多种组合使用方式

          本文链接:https://www.haomeiwen.com/subject/keaqcrtx.html