讲一下什么情况下RecyclerView回收复用会失效。
整体涉及链路
首先第一层RecyclerView,测量子View的地方,在linearLayoutManager的onLayoutChildren()
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
...
mLayoutState.mInfinite = resolveIsInfinite();
...
if (mAnchorInfo.mLayoutFromEnd) {
...
fill(recycler, mLayoutState, state, false);
...
}
}
//resolveIsInfinite()开始
boolean resolveIsInfinite() {
return mOrientationHelper.getMode() == View.MeasureSpec.UNSPECIFIED
&& mOrientationHelper.getEnd() == 0;
}
public static OrientationHelper createHorizontalHelper(RecyclerView.LayoutManager layoutManager) {
return new OrientationHelper(layoutManager) {
public int getEndAfterPadding() {
return this.mLayoutManager.getHeight() - this.mLayoutManager.getPaddingBottom();
}
public int getEnd() {
return this.mLayoutManager.getHeight();
}
}
}
//resolveIsInfinite结束
int fill(RecyclerView.Recycler recycler, LayoutState layoutState,
RecyclerView.State state, boolean stopOnFocusable) {
...
while ((layoutState.mInfinite || remainingSpace > 0) && layoutState.hasMore(state)) {
...
layoutChunk(recycler, state, layoutState, layoutChunkResult);
...
}
...
}
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
LayoutState layoutState, LayoutChunkResult result) {
...
measureChildWithMargins(view, 0, 0);
....
}
public void measureChildWithMargins(@NonNull View child, int widthUsed, int heightUsed) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child);
widthUsed += insets.left + insets.right;
heightUsed += insets.top + insets.bottom;
final int widthSpec = getChildMeasureSpec(getWidth(), getWidthMode(),
getPaddingLeft() + getPaddingRight()
+ lp.leftMargin + lp.rightMargin + widthUsed, lp.width,
canScrollHorizontally());
final int heightSpec = getChildMeasureSpec(getHeight(), getHeightMode(),
getPaddingTop() + getPaddingBottom()
+ lp.topMargin + lp.bottomMargin + heightUsed, lp.height,
canScrollVertically());
if (shouldMeasureChild(child, widthSpec, heightSpec, lp)) {
child.measure(widthSpec, heightSpec);
}
}
// 下面这个方法很关键,就不省略了。
public static int getChildMeasureSpec(int parentSize, int parentMode, int padding,
int childDimension, boolean canScroll) {
int size = Math.max(0, parentSize - padding);
int resultSize = 0;
int resultMode = 0;
if (canScroll) {
if (childDimension >= 0) {
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
switch (parentMode) {
case