需求:
要实现一个横向分页可滑动的显示效果,查了下网上的实现方式,发现一个效果一样的,参考连接如下:
一行代码让RecyclerView分页滚动
但是实现以后发现应用运行起来巨卡,参考了张旭童的文章(掌握自定义LayoutManager),发现这篇文中在onLayoutChildren中会遍历所有的子item并执行如下语句:
View view = recycler.getViewForPosition(index);
和同事一快优化时,同事说每次走这个都会走onCreateViewHolder,因此这个地方需要优化,在优化的过程中参考了以下原则:
1.通过getChildCount()和recycler.getScrapList().size() 查看当前屏幕上的Item数量 和 scrapCache缓存区域的Item数量,合格的LayoutManager,childCount数量不应大于屏幕上显示的Item数量,而scrapCache缓存区域的Item数量应该是0.
2.自己定义的adapter中onCreateViewHolder和onBindeViewHolder的打印次数。
如下是优化后的代码文件,大家可做参考,当然应用卡的根本原因是:应用调试一直是debug版本,打包成release后解决了这个问题,不过因为这个卡顿倒是好好看了一把recyclerview的复用和回收机制,更感谢一起优化的同事,废话不多说,上代码(显示效果是3行6列,因此一页是18个数据):
package com.hisense.recipe.recycleviewpage;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.View;
import com.hisense.fridge.foodmanage.utils.FoodLog;
import java.util.List;
import static com.hisense.recipe.view.magicindicator.ScrollState.SCROLL_STATE_IDLE;
public class HorizontalPageLayoutManager extends RecyclerView.LayoutManager implements PageDecorationLastJudge {
private final String TAG = HorizontalPageLayoutManager.class.getSimpleName();
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return null;
}
int totalHeight = 0;
int totalWidth = 0;
int offsetY = 0;
int offsetX = 0;
private int mFirstVisibleItemPos; //第一个可见的Item索引
private int endIndex;
private View firstView = null;
private SparseArray<Rect> allItemFrames = new SparseArray<>();
private SparseBooleanArray mHasAttachedItems = new SparseBooleanArray();//布局好的item
RecyclerView.Recycler mRecycler;
public HorizontalPageLayoutManager(int rows, int columns) {
this.rows = rows;
this.columns = columns;
this.onePageSize = rows * columns;
FoodLog.d(TAG, "rows = " + rows + ",columns = " + columns);
}
@Override
public boolean canScrollHorizontally() {
return true;
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (getChildCount() <= 0)