問題分析
最近使用RecyclerView的瀑布流樣式加載、顯示圖片柒桑,由于剛開始沒有進(jìn)行優(yōu)化弊决,會有Item切換、閃爍魁淳、跳頁等等等問題飘诗,體驗(yàn)甚是差呀,這就需要我們?nèi)?yōu)化改進(jìn)了界逛。
先考慮下昆稿,為什么會有這樣的問題呢?因?yàn)閳D片在加載的時(shí)候由于尺寸未知(特別是高度)息拜,所以Item需要重新計(jì)算自己的尺寸溉潭,這樣又會導(dǎo)致重繪净响,由于瀑布流一次會加載多張圖片,所以就產(chǎn)生了喳瓣,Item切換馋贤、閃爍、跳頁等問題畏陕。說到底就是在加載圖片前配乓,先確定Item的尺寸,避免Item重新計(jì)算自己的尺寸蹭秋。Item的尺寸如何確定呢扰付?那就要先得到要加載圖片的尺寸,然后設(shè)置給Item中的ImageView仁讨。
解決方案
網(wǎng)上有的說法是對StaggeredGridLayoutManager進(jìn)行如下設(shè)置:
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
經(jīng)測試羽莺,確實(shí)解決了Item左右切換的問題,但是滑動時(shí)候每一列還是會跳動洞豁,同時(shí)頂部和底部有空白盐固。繼續(xù)優(yōu)化吧。
我們的圖片data是網(wǎng)絡(luò)請求獲得的丈挟,得到data后先進(jìn)行一次處理:
@Override
public void onSuccess(List<GirlItemData> data) {
DataService.startService(mActivity, data, mSubtype);
}
通過啟動一個(gè)IntentService刁卜,根據(jù)圖片的url,獲得對應(yīng)的Bitmap曙咽,進(jìn)而得到圖片的尺寸信息:
public class DataService extends IntentService {
public DataService() {
super("");
}
public static void startService(Context context, List<GirlItemData> datas, String subtype) {
Intent intent = new Intent(context, DataService.class);
intent.putParcelableArrayListExtra("data", (ArrayList<? extends Parcelable>) datas);
intent.putExtra("subtype", subtype);
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent == null) {
return;
}
List<GirlItemData> datas = intent.getParcelableArrayListExtra("data");
String subtype = intent.getStringExtra("subtype");
handleGirlItemData(datas, subtype);
}
private void handleGirlItemData(List<GirlItemData> datas, String subtype) {
if (datas.size() == 0) {
EventBus.getDefault().post("finish");
return;
}
for (GirlItemData data : datas) {
Bitmap bitmap = ImageLoader.load(this, data.getUrl());
if (bitmap != null) {
data.setWidth(bitmap.getWidth());
data.setHeight(bitmap.getHeight());
}
data.setSubtype(subtype);
}
EventBus.getDefault().post(datas);
}
}
最后將尺寸信息封裝到data中蛔趴,并通過EventBus傳回。
為什么要用IntentService呢例朱?因?yàn)樗谧泳€程執(zhí)行孝情,執(zhí)行完后自動結(jié)束,同時(shí)我們獲得Bitmap是通過Glide洒嗤,只能在子線程進(jìn)行箫荡,畢竟這個(gè)過程是個(gè)耗時(shí)操作,所以子線程加持的IntentService還是省心省事的渔隶。
得到EventBus返回的data羔挡,就是刷新Adapter了,看一下Adapter中的操作:
@Override
protected void convert(RecyclerView.ViewHolder viewHolder, GirlItemData girlItemData) {
ViewHolder holder = (ViewHolder) viewHolder;
ScaleImageView imageView = holder.getView(R.id.girl_item_iv);
imageView.setInitSize(girlItemData.getWidth(), girlItemData.getHeight());
ImageLoader.load(NiceReadApplication.getContext(), girlItemData.getUrl(), imageView);
}
其實(shí)ScaleImageView重寫了ImageView的onMeasure方法间唉,我們將圖片的寬高設(shè)置給ScaleImageView绞灼,然后再加載圖片。
效果
最后我們來對比下前后的效果: