返回介绍

目标

发布于 2025-01-04 00:12:06 字数 3755 浏览 0 评论 0 收藏 0

Glide 中的目标作为请求跟请求者之间的传递者。目标负责显示占位符,加载的资源以及为每个请求确定合适的尺寸。最常用目标是使用 ImageView 显示占位符,Drawable 和 Bitmap 的 ImageViewTarget。用户还可以实现自己的目标,或者对任何可用的基类进行子类化。

指定目标

into(Target) 方法不仅用于启动每个请求,同时也可以指定将要接收请求结果的目标。Glide 提供了一个辅助方法给 into(ImageView) ,其采用 ImageView 并把它包装在目标于适合所请求的资源类型。

为了方便使用自定义目标,这些 into() 方法返回提供给他们的目标:

Target<Bitmap> target = Glide.with(fragment)
        .asBitmap()
        .load(url)
        .into(imageView);
...
// Some time later:
Glide.with(fragment).clear(target);

目标和自动取消

目标可以并且通常应该被重新用于相同的地方显示的每个后续请求。重新使用目标允许 Glide 在新加载启动时自动取消并且重新使用之前负载的资源。未能重新使用目标可能会导致之前请求中的资源替换较新的请求。

自定义目标

重新使用自定义目标的一种简单方法是简单地将其作为实例变量:

private class WidgetHolder {
  private final Fragment fragment;
  private final Target<Widget> widgetTarget;

  public WidgetHolder(Fragment fragment, Widget widget) {
    this.fragment = fragment;
    widgetTarget = new CustomWidgetTarget(widget);
  }

  public void showInWidget(Uri uri) {
    Glide.with(fragment)
        .load(uri)
        .into(widgetTarget);
  }
}

Glide 能够使用 getRequest() 和 setRequest() 方法查找和取消对目标的请求。这意味着所有自定义的目标都必须实现这些方法。最简单的方法是进行子类化 BaseTarget。

ViewTargets

一些自定义的目标还可以提供更智能的 getRequest() 和 setRequest() 实现,避免严格要求重新使用目标。例如,ViewTarget 使用 Android Framework 的 getTag()和 setTag()方法:

@Override
public Request getRequest() {
    return (Request) view.getTag();
}

@Override
public void setRequest(Request request) {
    view.setTag(request);
}

由于标签是 View 的属性,因此新加载的 ViewTargets 可以查找和取消/重新使用先前 ViewTargets 的请求。因此,当使用 into(ImageView) 或 ViewTarget 的子类加载到视图中时,您可以为每个加载传递新的目标:

@Override
public void onBindViewHolder(ViewHolder vh, int position) {
  int resourceId = resourceIds.get(position)
  Glide.with(fragment)
      .load(resourceId)
      .into(new CustomViewTarget(vh.imageView));

尺寸

默认情况下,Glide 使用由 Targets 提供的 getSize() 大小作为请求的目标大小。这样做可以让 Glide 选择适当的 url,downsample,crop 和转换适当的图像,以尽量减少内存使用,并确保负载尽可能快。

最简单的实现方式是在 getSize() 方法中立即调用回调函数:

@Override
public void getSize(SizeReadyCallback cb) {
  cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}

您还可以将尺寸传递给您的 Target 的构造函数,并将这些尺寸提供给回调:

public class CustomTarget<T> implements Target<T> {
  private final int width;
  private final int height;

  public CustomTarget(int width, int height) {
    this.width = width;
    this.height = height;
  }

  ...

  @Override
  public void getSize(SizeReadyCallback cb) {
    cb.onSizeReady(width, height);
  }
}

查看目标

ViewTarget 实现了 getSize() 方法,通过检查 View 的属性或者使用 onPreDrawListener 在渲染之前立即测量视图来实现。我们采用下面的逻辑:

  1. 如果任一视图的尺寸设置的值>0,则使用这些尺寸。
  2. 如果任一视图的尺寸设置成 WRAP_CONTENT,则使用屏幕的宽度或高度。
  3. 如果至少有一个视图的尺寸的值<=0 而不是 WRAP_CONTENT,则添加一个 OnPreDrawListener 来监听布局。

WRAP_CONTENT

请注意,Glide 不能很好的处理 WRAP_CONTENT,这是因为对于我们来说很难清楚用户的意图,特别是要求转换时。

我们可以看作 WRAP_CONTENT 是用户请求原始的未修改的图像,但是这样做在我们加载大图像时有内存溢出的风险。另外,特别是视图不会脱离屏幕,因此 Android 框架可能会最终缩小任何加载成功的全分辨率图像。

使用屏幕尺寸,我们至少可以对超大图像进行降低采样,而不会完全忽略用户的请求。

应用视图大小

一般来说,当在其加载的视图上设置显示 dp 大小时,Glide 提供了最快的和最可预测的结果。然而,当不可能这样时,Glide 还为布局权重,MATCH_PARENT 和其他相对尺寸提供了强大的支持 OnPreDrawListeners。最后,如果这些都没有设置,Glide 应该为 WRAP_CONTENT 提供了合理的行为。

备选方案

如果在任何情况下,Glide 似乎都会使 View 大小错误,您可以随时通过扩展 ViewTarget 和实现自己的逻辑来手动覆盖大小,或者通过使用 RequestOptions 中的 override() 方法。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文