揭祕之從RecyclerView滑動監聽到Gilde平滑載入圖片
本文應該是RecyclerView的第三篇,今天來講講如何讓RecyclerView優先載入可見item,如何在RecyclerView滑動中停止圖片的載入保證頁面流暢。
先看效果圖:
讓我們來回顧一下陳舊的Listview,如果item中有網路圖片,那時候我們怎麼做的呢?我們要注意一下幾個重點:
1.網路圖片獲取
2.網路圖片二級快取(至少一級快取)
3.在高速滑動時候停止圖片載入執行緒
4.在低速滑動,停止滑動時候開啟執行緒
5.下拉重新整理
6.上滑載入
7.優先載入可見item
如果不用第三方框架,自己維護執行緒池等等東西,想想都複雜。而如今我們不需要這些東西了,本文的Dome輕輕鬆鬆做到這7點。
首先1 2 glide給予我們完美的支援,5 6 我前文提到過的RecyclerView也有完美的支援。今天主要講 3 4 7這三點如何實現。
首先看7.優先載入可見item,之前在listview我們可能這樣做,寫個滑動監聽並且獲取可見item的位置,然後載入對應圖片,那麼我們使用RecyclerView+Gilde到底如何做這一點呢,筆者一開始也有些猶豫,於是直接issues到了github :
看來老外對於自己的親兒子專案還是很關愛的生怕我不懂啪啪啪舉了幾個例子,我只好用CET3.9的水平翻譯一下了。
我的意思是當glide和recyclerview配合使用的時候,glide會不會優先載入可見item。
TWiStErRob大概說,所有的載入優先順序都是預設的,但是可以通過設定priority來這是優先順序,但是不是在特別的情況下這個方法一般不被使用,他舉了個例子說,如果一個item中有3個圖片,他們的資訊有重疊的部分,其中有一張圖是最重要,資訊最全的時候,可以提高這張圖的優先順序。
然而TWiStErRob給我的答案似乎並沒有理解我想問的(可能是我CET3.9)的原因,我想算啦吧,問別人不如自己實踐出來的更真實。於是我準備出如下場景:
1.網速很渣(因為速度快瞬間載入完很多圖難以測試)
2.開啟一個遊戲的下載(先把比較渣的網速給我佔了!)
3.item比較多
4.當前可見item比較少
5.設定Glide跳過二級快取
6.對Glide載入成功進行監聽並且列印圖片對應位置log
Glide.with(mContext).load(data.URl)
.placeholder(R.mipmap.ic_launcher)
.centerCrop()
.skipMemoryCache(skipcache)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(new GlideDrawableImageViewTarget(productHolder.imgRight ) {
@Override
public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) {
super.onResourceReady(drawable, anim);
Log.d("-------------------+", "" + (position+1));
}
首先進來緩慢滑動幾次:
前四張圖片被載入了符合預期。
接下來我們快速滑動到底部:
如我所料,優先載入了可見的底部的item。
到這裡7問題就解決了。我們以正缺的姿勢去使用RecyclerView+Gilde就可以了。
接下來是:
3.在高速滑動時候停止圖片載入執行緒
4.在低速滑動,停止滑動時候開啟執行緒
RecyclerView是可以滑動監聽的但是別高興的太早:
SuperRefreshRecyclerView.一臉懵逼
你點不出設定滑動監聽方法,其實是這樣的:
public class SuperRefreshRecyclerView extends FrameLayout {
private RelativeLayout emptyView,errorView;
private SwipeToLoadLayout swipeToLoadLayout;
private SwipeLoadMoreFooterLayout swipeLoadMoreFooterLayout;
private RecyclerView recyclerView;
SuperRefreshRecyclerView中有個原聲的RecyclerView所以我們肯定不能直接.到RecyclerView的方法了。於是決定自己寫個callback介面就好了:
public interface ChangeScrollStateCallback {
public void change(int c);
}
然後提供set方法:
public void setChangeScrollStateCallback(ChangeScrollStateCallback mChangeScrollStateCallback){
this.mChangeScrollStateCallback=mChangeScrollStateCallback;
}
並在Activity中呼叫:
superRecyclerView.setChangeScrollStateCallback(new ChangeScrollStateCallback() {
//0 表示停止滑動的狀態 SCROLL_STATE_IDLE
//1表示正在滾動,使用者手指在螢幕上 SCROLL_STATE_TOUCH_SCROLL
//2表示正在滑動。使用者手指已經離開螢幕 SCROLL_STATE_FLING
@Override
public void change(int c) {
switch (c) {
case 2:
Glide.with(MainActivity.this).pauseRequests();
Log.d("AAAAAAAAAAAAAAA", "暫停載入" + c);
break;
case 0:
Glide.with(MainActivity.this).resumeRequests();
Log.d("AAAAAAAAAAAAAAA","恢復載入" + c);
break;
case 1:
Glide.with(MainActivity.this).resumeRequests();
Log.d("AAAAAAAAAAAAAAA", "恢復載入" + c);
break;
}
}
});
Glide提供的暫停恢復方法有沒有很爽:
Glide.with(MainActivity.this).pauseRequests();
Glide.with(MainActivity.this).resumeRequests();
高速滑動一下螢幕:
緩慢滑動螢幕:
一切符合預期,1-7點我們就這樣輕鬆的完成了。同事也給大家建議,在懷疑一個地方的時候不妨打斷點打日誌去看看到底是怎麼回事,不斷提高自己解決問題的能力,不要只會問而不會做。
歡迎關注作者。歡迎評論討論。歡迎拍磚。
如果覺得這篇文章對你有幫助,歡迎打賞,
歡迎star,Fork我的github。
喜歡作者的也可以Follow。也算對作者的一種支援。
本文Github程式碼連結
https://github.com/AndroidMsky/GlideScrollRecyclerView
歡迎加作者自營安卓開發交流群:308372687