下面内容是以水平方向上的LinearLayoutManager作为演示
AbstractHolder.java 抽象Adapter, 主要是为了避免在onBindViewHolder中做太多事情,内容如下:
public AbstractHolder(View itemView) {
super(itemView);
}
public abstract void onBind(XXX mo);
public abstract void updateUI(XXX mo);
public abstract void onUnBind();
不同item元素的样式不同是通过getItemViewType来确定,默认为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) {
//根据对象获取具体的元素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);
// 处理一些资源回收的事情
}
常用的性能优化
// 提前占坑,默认为2
LinearLayoutManager lm = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
lm.setInitialPrefetchItemCount(5);
// 设置缓存
rvDevices.setItemViewCacheSize(200);
// 设置部分或固定的尺寸
rvDevices.setHasFixedSize(true);
// 滚动事件派发
rvDevices.setNestedScrollingEnabled(false);
// ConstrainLayout作为根布局元素,避免过分嵌套.
RecyclerView仿ViewPager的左右滑动切换
int offsetX; // 滑动偏移,确保下一个页面的位置
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时根据偏移切换索引.
recyclerview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
//滑动距离超过recycleview的0.2倍宽度时换页
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延迟加载
避免页面内item/viewType过多卡顿问题,延迟UI加载时机至滑动停止后再加载可见的holder.
Note:需提前给默认的页面元素设置UI占位内容,避免一片灰白。可参考github上的空白占位. 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: //列表静止时才加载UI及绑定事件,以解决列表滑动时卡顿的问题
deviceAdapter.setCanInitView(true);
deviceAdapter.notifyDataSetChanged();
break;
case RecyclerView.SCROLL_STATE_DRAGGING: //正在用手指拖动
case RecyclerView.SCROLL_STATE_SETTLING: //松手后的惯性滚动
deviceAdapter.setCanInitView(false);
break; }
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});