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<String> sizeProvider = new FixedPreloadSizeProvider<>(650, 650);

這樣就完成了第一步。

2、創建一個 PreloadModelProvider

先展示下代碼:

public class MyPreloadModelProvider implements ListPreloader.PreloadModelProvider<String> {

    private Context context;
    private List<String> urls;

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

    @NonNull
    @Override
    public List<String> 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<String> 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的緩存或直接清除應用緩存,然後聯網進入圖片列表頁,進行很小範圍滑動,之後斷網,然後向上滑動觀察滑動出來的圖片有沒有顯示出來,如果顯示了則表示預加載是成功的。

效果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章