Glide RecyclerView插件

关于

RecyclerView 集成库使你在你的应用中能够使用 RecyclerViewPreloader ,它可以在用户滑动 RecyclerView 时自动加载稍微超前一些的图片。

配合使用正确的图片尺寸和高效率的磁盘缓存策略,这个库可以显著减少用户滑动图片列表时看到的加载指示器的数量。

Gradle 依赖

要使用 RecyclerView 集成库,在你的 build.gradle 文件中添加一个依赖:

compile (“com.github.bumptech.glide:recyclerview-integration:4.3.0”) {
// Excludes the support library because it’s already included by Glide.
transitive = false
}
当然你还需要确保你的应用中有 RecyclerView 的依赖并正在你的应用中使用 RecyclerView :) 。

设置

为了使用 RecyclerView 集成库,你需要做以下步骤:

  1. 创建一个 PreloadSizeProvider
  2. 创建一个 PreloadModelProvider
  3. 创建一个 RecyclerViewPreloader 并将你前两步创建的 PreloadSizeProvider 和 PreloadModelProvider 赋值进去
  4. 将你的 RecyclerViewPreloader 添加到你的 RecyclerView 做为一个 scroll listener。
    上面的每一个步骤在下面会详细讲解。

PreloadSizeProvider

在添加完 gradle 依赖后,你接下来需要创建一个 PreloadSizeProvider。PreloadSizeProvider 负责保证你的 RecyclerViewPreloader 使用与你的适配器中 onBindViewHolder 方法一样的尺寸来加载图片。

如果你的 RecyclerView 里有统一的 View 尺寸、你使用 into(ImageView)来加载图片并且你没有使用 override() 方法来设置一个不同的尺寸,那么你可以使用 ViewPreloadSizeProvider。

如果你使用 override() 方法或其他情况导致加载的图片尺寸并不完全匹配你的 View 尺寸,你可以使用 FixedPreloadSizeProvider。

如果在你的 RecyclerView 中决定给定位置下图片尺寸的逻辑并不适合上述两种场景,你还可以编写你自己的 [PreloadSizeProvider]的实现。

如果你使用固定尺寸加载你的图片,通常 FixedPreloadSizeProvider 是最简单的:

private final imageWidthPixels = 1024;
private final imageHeightPixels = 768;

...

PreloadSizeProvider sizeProvider = 
    new FixedPreloadSizeProvider(imageWidthPixels, imageHeightPixels);

PreloadModelProvider

下一步是实现你的 PreloadModelProvider。PreloadModelProvider主要做两个事情,第一个是收集并返回一个给定位置的 Model(即你传给 Glide 的 load(Object) 方法的对象,例如 URL 或 文件路径)列表。第二是取出一个 Model 并生产一个 RequestBuilder,用于预加载给定的 Model 到内存中。

例如,假设我们有一个 RecyclerView,它包含一个图片的 url 列表,RecyclerView的每个位置展示一个 URL 。然后,假设你在你的 RecyclerView.Adapter 的 onBindViewHolder 方法中这样加载图片:

private List<String> myUrls = ...;

...

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
  ImageView imageView = ((MyViewHolder) viewHolder).imageView;
  String currentUrl = myUrls.get(position);

  GlideApp.with(fragment)
    .load(currentUrl)
    .override(imageWidthPixels, imageHeightPixels)
    .into(imageView);
}

这样的话,你的 PreloadModelProvider 实现大概看起来像这样:

private List<String> myUrls = ...;

...

private class MyPreloadModelProvider implements PreloadModelProvider {
  @Override
  @NonNull
  List<U> getPreloadItems(int position) {
    String url = myUrls.get(position);
    if (TextUtils.isEmpty(url)) {
      return Collections.emptyList();
    }
    return Collections.singletonList(url);
  }

  @Override
  @Nullable
  RequestBuilder getPreloadRequestBuilder(String url) {
    return 
      GlideApp.with(fragment)
        .load(url) 
        .override(imageWidthPixels, imageHeightPixels);
  }
}

有一点十分重要,从 getPreloadRequestBuilder 中返回的 RequestBuilder ,必须与你从 onBindViewHolder 里启动的请求使用完全相同的一组选项 (占位符, 变换等) 和完全相同的尺寸。如果对于一个给定位置,两种方法提供的任何选项不完全相同,你的预加载请求将被浪费,因为它加载的图片会被缓存,但是缓存键却与你在 onBindViewHolder 里图片的缓存键不同。如果您无法使这些缓存键匹配,请参阅调试页面。

如果对于一个给定的位置你不需要加载任何东西,你可以从 getPreloadItems 返回一个空列表。如果你稍晚时候发现你无法从一个给定的 Model 创建一个 RequestBuilder,你可以从 getPreloadRequestBuilder 方法返回 null 。

RecyclerViewPreloader

当你创建好你的 PreloadSizeProvider 和 PreloadModelProvider,你就已经准备好创建 RecyclerViewPreloader 了:

private final imageWidthPixels = 1024;
private final imageHeightPixels = 768;
private List<String> myUrls = ...;

...

PreloadSizeProvider sizeProvider = 
    new FixedPreloadSizeProvider(imageWidthPixels, imageHeightPixels);
PreloadModelProvider modelProvider = new MyPreloadModelProvider();
RecyclerViewPreloader<Photo> preloader = 
    new RecyclerViewPreloader<>(
        Glide.with(this), modelProvider, sizeProvider, 10 /*maxPreload*/);

这里使用 10 作为 maxPreload 仅仅十个占位符,关于如何选择这个数字更详细的讨论,请直接看下一节。

maxPreload

maxPreload 是一个整数,指示你想预加载多少条数据。最优解因你的图片尺寸,质量,RecyclerView 的布局而异,有些时候甚至与你的应用所运行的设备有关。

一个好的起点是,选择一个足够大的数,大到能包含两到三行的所有图片。一旦你选择了你的初始数字,你可以尝试在几个不同的设备上运行你的应用,并做必要的微调来最大化缓存命中率。

一个过大的数字将意味着你预加载得过远,不实用。过小的数字则会阻止你提前加载足够的图片。

RecyclerView

最后一步,当你拥有你的 RecyclerViewPreloader 之后,就可以将它添加为你的 RecyclerView 的一个滑动监听器:

RecyclerView myRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
myRecyclerView.addOnScrollListener(preloader);

将 RecyclerViewPreloader 添加为一个滑动监听器,将允许 RecyclerViewPreloader 自动提前加载用户滑动方向上的图片,并监听滑动方向和加速度的改变。

警告 - Glide 的默认滑动监听器 RecyclerToListViewScrollListener 假定你在使用一个 LinearLayoutManager 或其子类,如果实际情况并非如此将会发生 crash 。如果你在使用不同的 LayoutManager 类型,你需要实现你自己的 OnScrollListener,并翻译一下 RecyclerView 提供位置的调用,以及 RecyclerViewPreloader 关于这些位置的调用。

总体代码

当你完成了上述步骤之后,你的代码看起来应该类似这样:

public final class ImagesFragment extends Fragment {
  // These are totally arbitrary, pick sizes that are right for your UI.
  private final imageWidthPixels = 1024;
  private final imageHeightPixels = 768;
  // You will need to populate these urls somewhere...
  private List<String> myUrls = ...;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {

    View result = inflater.inflate(R.layout.images_fragment, container, false);

    PreloadSizeProvider sizeProvider = 
        new FixedPreloadSizeProvider(imageWidthPixels, imageHeightPixels);
    PreloadModelProvider modelProvider = new MyPreloadModelProvider();
    RecyclerViewPreloader<Photo> preloader = 
        new RecyclerViewPreloader<>(
            Glide.with(this), modelProvider, sizeProvider, 10 /*maxPreload*/);

    RecyclerView myRecyclerView = (RecyclerView) result.findViewById(R.id.recycler_view);
    myRecyclerView.addOnScrollListener(preloader);

    // Finish setting up your RecyclerView etc.
    myRecylerView.setLayoutManager(...);
    myRecyclerView.setAdapter(...);

    ... 

    return result;
  }

  private class MyPreloadModelProvider implements PreloadModelProvider {
    @Override
    @NonNull
    public List<U> getPreloadItems(int position) {
      String url = myUrls.get(position);
      if (TextUtils.isEmpty(url)) {
        return Collections.emptyList();
      }
      return Collections.singletonList(url);
    }

    @Override
    @Nullable
    public RequestBuilder getPreloadRequestBuilder(String url) {
      return 
        GlideApp.with(fragment)
          .load(url) 
          .override(imageWidthPixels, imageHeightPixels);
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值