下面內(nèi)容是以水平方向上的LinearLayoutManager作為演示
AbstractHolder.java 抽象Adapter, 主要是為了避免在onBindViewHolder中做太多事情,內(nèi)容如下:
public AbstractHolder(View itemView) {
super(itemView);
}
public abstract void onBind(XXX mo);
public abstract void updateUI(XXX mo);
public abstract void onUnBind();
不同item元素的樣式不同是通過(guò)getItemViewType來(lái)確定,默認(rèn)為0。具體Adapter如下,僅展示具體代碼.
@NonNull
@Override
public AbstractHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
AbstractHolder holder = null;
View v;
switch (viewType) {
case MOUtils.DEV_ViewType_0:
break;
case MOUtils.DEV_ViewType_1:
break;
case MOUtils.DEV_ViewType_2:
break;
case MOUtils.DEV_ViewType_3:
break;
case MOUtils.DEV_ViewType_4:
break;
}
return holder;
}
@Override
public void onBindViewHolder(@NonNull AbstractHolder holder, int position) {
MOBase mo = mMOList.get(position);
holder.onBind(mo);
}
@Override
public int getItemCount() {
return mMOList.size();
}
@Override
public long getItemId(int position) {
return mSoleID.getAndIncrement();
}
@Override
public int getItemViewType(int position) {
//根據(jù)對(duì)象獲取具體的元素style.
MOBase mo = mMOList.get(position);
return MOUtils.getMOViewType(mo);
}
@Override
public void onViewRecycled(@NonNull AbstractHolder holder) {
super.onViewRecycled(holder);
// 處理一些資源回收的事情
}
@Override
public void onViewDetachedFromWindow(@NonNull AbstractHolder holder) {
super.onViewDetachedFromWindow(holder);
// 處理一些資源回收的事情
}
常用的性能優(yōu)化
// 提前占坑,默認(rèn)為2
LinearLayoutManager lm = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
lm.setInitialPrefetchItemCount(5);
// 設(shè)置緩存
rvDevices.setItemViewCacheSize(200);
// 設(shè)置部分或固定的尺寸
rvDevices.setHasFixedSize(true);
// 滾動(dòng)事件派發(fā)
rvDevices.setNestedScrollingEnabled(false);
// ConstrainLayout作為根布局元素,避免過(guò)分嵌套.
RecyclerView仿ViewPager的左右滑動(dòng)切換
int offsetX; // 滑動(dòng)偏移,確保下一個(gè)頁(yè)面的位置
recyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
offsetX = 0;
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
offsetX += dx;
super.onScrolled(recyclerView, dx, dy);
}
});
// UP時(shí)根據(jù)偏移切換索引.
recyclerview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
//滑動(dòng)距離超過(guò)recycleview的0.2倍寬度時(shí)換頁(yè)
if (offsetX <= -mRcContainer.getWidth() * 0.2) {
currIndex -= 1;
currIndex = (currIndex < 0) ? 0: currIndex;
} else if (offsetX >= mRcContainer.getWidth() * 0.2) {
currIndex += 1;
currIndex = currIndex > adapter.getItemCount() ? adapter.getItemCount()-1 : currIndex;
}
mRcContainer.smoothScrollToPosition(currIndex);
return true;
}
return false;
}
});
UI延遲加載
避免頁(yè)面內(nèi)item/viewType過(guò)多卡頓問(wèn)題,延遲UI加載時(shí)機(jī)至滑動(dòng)停止后再加載可見的holder.
Note:需提前給默認(rèn)的頁(yè)面元素設(shè)置UI占位內(nèi)容,避免一片灰白??蓞⒖糶ithub上的空白占位. https://github.com/sharish/ShimmerRecyclerView
//Adapter onBind
@Override
public void onBindViewHolder(@NonNull AbstractHolder holder, int position) {
if (canInitView) {
MOBase mo = mMOList.get(position);
holder.onBind(mo);
}
}
// recyclerview
rvDevices.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE: //列表靜止時(shí)才加載UI及綁定事件,以解決列表滑動(dòng)時(shí)卡頓的問(wèn)題
deviceAdapter.setCanInitView(true);
deviceAdapter.notifyDataSetChanged();
break;
case RecyclerView.SCROLL_STATE_DRAGGING: //正在用手指拖動(dòng)
case RecyclerView.SCROLL_STATE_SETTLING: //松手后的慣性滾動(dòng)
deviceAdapter.setCanInitView(false);
break; }
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});