一、引入
最近在研究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的緩存或直接清除應用緩存,然後聯網進入圖片列表頁,進行很小範圍滑動,之後斷網,然後向上滑動觀察滑動出來的圖片有沒有顯示出來,如果顯示了則表示預加載是成功的。
效果: