Glide集成RecyclerView实现列表滑动图片预加载

一、引入

最近在研究Glide高级用法时看到可以结合RecyclerView,实现在用户滑动 RecyclerView 时自动加载稍微超前一些图片的功能,从而显著减少用户滑动图片列表时看到占位图的几率,很好得提升用户的滑动体验。然后除了官网之外,没有比较详细的文章,所以便写下这篇以帮助有需要的伙伴。

二、前提

读这篇文章前需要先了解Glide和RecyclerView的基础,了解后我们进入下面的环节。

三、总体思路

1、创建一个 PreloadSizeProvider;
2、创建一个 PreloadModelProvider;
3、创建一个 RecyclerViewPreloader 并将你前两步创建的 PreloadSizeProvider 和 PreloadModelProvider 赋值进去;
4、将你的 RecyclerViewPreloader 添加到你的 RecyclerView 做为一个 scroll listener。
接下来我们一步步来实现

四、具体实现

1、添加依赖
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
//RecyclerView集成库
implementation("com.github.bumptech.glide:recyclerview-integration:4.9.0") {
    // Excludes the support library because it's already included by Glide.
	transitive = false
}
2、创建一个 PreloadSizeProvider

Glide 内置两个默认的 PreloadSizeProvider 实现:

ViewPreloadSizeProvider
FixedPreloadSizeProvider

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

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

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

这里简单起见,我们选择使用 FixedPreloadSizeProvider :

FixedPreloadSizeProvider sizeProvider = new FixedPreloadSizeProvider<>(650, 650);

这样就完成了第一步。

2、创建一个 PreloadModelProvider

先展示下代码:

public class MyPreloadModelProvider implements ListPreloader.PreloadModelProvider {

    private Context context;
    private List urls;

    public MyPreloadModelProvider(Context context, List urls) {
        this.context = context;
        this.urls = urls;
    }

    @NonNull
    @Override
    public List getPreloadItems(int position) {
        String url = urls.get(position);
        if (TextUtils.isEmpty(url)) {
            return Collections.emptyList();
        }
        return Collections.singletonList(url);
    }

    @Nullable
    @Override
    public RequestBuilder getPreloadRequestBuilder(@NonNull String item) {
        //返回的 RequestBuilder ,必须与你从 onBindViewHolder 里启动的请求使用完全相同的一组选项 (占位符, 变换等) 和完全相同的尺寸
        return Glide.with(context)
                .load(item)
                .centerCrop();
    }
}

自定义 PreloadModelProvider 需要实现两个方法,
一个是getPreloadItems(int position),作用是收集并返回一个给定位置的 Model(即你传给 Glide 的 load(Object) 方法的对象,例如 URL 或 文件路径)列表。这里我使用的是图片链接;
另一个方法是getPreloadRequestBuilder(@NonNull String item),取出一个 Model 并生产一个 RequestBuilder,用于预加载给定的 Model 到内存中。这里比较关键的是返回的 RequestBuilder ,必须与你从 onBindViewHolder 里启动的请求使用完全相同的一组选项 (占位符, 变换等) 和完全相同的尺寸,因为如果指定的图片尺寸、占位图、圆角变幻等不一致时Glide缓存的key也会不一致,导致用户滑动时图片缓存是找不到的。
这里的泛型对应的是图片链接,是String类型,你也可以指定为具体的实体类。
然后实例化PreloadModelProvider

MyPreloadModelProvider preloadModelProvider = new MyPreloadModelProvider(this, urls);

第二个参数是图片url的列表。

3、创建一个 RecyclerViewPreloader 并将你前两步创建的 PreloadSizeProvider 和 PreloadModelProvider 赋值进去
RecyclerViewPreloader preloader = new RecyclerViewPreloader<>(Glide.with(this), preloadModelProvider,
                sizeProvider, 10);

这里的preloadModelProvider和sizeProvider便是我们上面2步我们创建的对象,第三个参数表示你想预加载多少条数据,推荐的是预加载两到三行的所有图片。

4、将你的 RecyclerViewPreloader 添加到你的 RecyclerView 做为一个 scroll listener

这步比较简单,我们都熟悉:

recyclerView.addOnScrollListener(preloader);

然后贴一下ViewHolder的onBindViewHolder()方法,和上面第2步的RequestBuilder创建一致:

public void bindView(String url) {
        Glide.with(context)
                .load(url)
                .centerCrop()
                .into(imageView);
    }

五、验证

代码写完后运行,然后进行验证是否提前进行了预加载。先清除Glide的缓存或直接清除应用缓存,然后联网进入图片列表页,进行很小范围滑动,之后断网,然后向上滑动观察滑动出来的图片有没有显示出来,如果显示了则表示预加载是成功的。

效果:

你可能感兴趣的:(个人总结或心得)