The most painful thing for a programmer ape is that it took nine bulls and two bulls to find out the problem and solve it. So we have to pay attention to everything. This ape only realized this when we did another iteration recently.
Iterative requirements: To make a headline-like thing, there will be demographics in three places, and the data in three places must be consistent. To be more specific, I have to go back to the location under the channel I am currently choosing to see which location is coming in from different places. At this time, we just record the channel we read last time, the corresponding data and the position we read. Record the reading position, using the findFirstCompletely VisibleItemPosition () method. At this time, the test girl found that I asked questions. Sometimes the position would be restored. Sometimes the position would not be restored, but to the previous position. Then the author printed out the position when it was reserved and looked at it, and found that when the content of your Recycler View item exceeded one screen. FindFirstCompletely VisibleItemPosition () returns - 1, and the error happens. There's no way to hide from the source code, so let's go and see how Google works.
public int findFirstCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), true, false);
return child == null ? NO_POSITION : getPosition(child);
}
public static final int NO_POSITION = -1;
If not, when the findOneVisibleChild() method returns a child of null, findFirstCompletelyVisibleItemPosition returns - 1 and continues to look at findOneVisibleChild:
View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible,
boolean acceptPartiallyVisible) {
ensureLayoutState();
final int start = mOrientationHelper.getStartAfterPadding();
final int end = mOrientationHelper.getEndAfterPadding();
final int next = toIndex > fromIndex ? 1 : -1;
View partiallyVisible = null;
for (int i = fromIndex; i != toIndex; i+=next) {
//Find item
final View child = getChildAt(i);
//Return to the beginning of view, excluding his margin and decorations
final int childStart = mOrientationHelper.getDecoratedStart(child);
final int childEnd = mOrientationHelper.getDecoratedEnd(child);
//The child's location is within the scope of Recycler View
if (childStart < end && childEnd > start) {
if (completelyVisible) {
//When your Item is above Recycler View, it obviously does not work.
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
} else {
return child;
}
}
}
return partiallyVisible;
}
Return to the layout, where RecycvlerView begins and ends
/**
* Returns the start position of the layout after the start padding is added.
*
* @return The very first pixel we can draw.
*/
public abstract int getStartAfterPadding();
/**
* Returns the end position of the layout after the end padding is removed.
*
* @return The end boundary for this layout.
*/
public abstract int getEndAfterPadding();
Returns the number of item s visible
//getChildCount of RecyclerView
* Return the current number of child views attached to the parent RecyclerView.
* This does not include child views that were temporarily detached and/or scrapped.
*
* @return Number of attached children
*/
public int getChildCount() {
return mChildHelper != null ? mChildHelper.getChildCount() : 0;
}
//getChildCount of ChildHelp
* Returns the number of children that are not hidden.
*
* @return Number of children that are not hidden.
* @see #getChildAt(int)
*/
int getChildCount() {
return mCallback.getChildCount() - mHiddenViews.size();
}
Through the above in-depth analysis of findOne VisibleChild () method, it can be concluded that:
1. When the Item height is higher than RecyclerView height, the parameters passed in the findFirstCompletelyVisibleItemPosition method make the View: partiallyVisible defined in the findOneVisibleChild() method null when it is not assigned back.
public int findFirstCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), true, false);
return child == null ? NO_POSITION : getPosition(child);
}
//Code in findOneVisibleChild method
if (completelyVisible) {
//When your Item exceeds Recycler View, the following conditions are not valid.
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
2. When the Item height is higher than the RecyclerView height, the parameters passed in by the findFirstVisibleItemPosition method make the View: partiallyVisible defined in the findOneVisibleChild() method assign to child and return.
public int findFirstVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), false, true);
return child == null ? NO_POSITION : getPosition(child);
}
//Code in findOneVisibleChild method
if (completelyVisible) {
//Item is above RecyclerView height and acceptPartiallyVisible is true,partiallyVisibler is not assigned
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
3. When the Item height is higher than the RecyclerView height, the parameters passed in by the findLastVisibleItemPosition method make the View: partiallyVisible defined in the findOneVisibleChild() method assign to child and return.
public int findLastVisibleItemPosition() {
final View child = findOneVisibleChild(getChildCount() - 1, -1, false, true);
return child == null ? NO_POSITION : getPosition(child);
}
//for loop in findOneVisibleChild method executes once
if (completelyVisible) {
//Item is above RecyclerView height and acceptPartiallyVisible is false,partiallyVisibler is assigned
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
4. When the Item height is higher than the RecyclerView height, the parameters passed in by the findLastCompletelyVisibleItemPosition method make the View: partiallyVisible defined in the findOneVisibleChild() method null when it is not assigned back.
public int findLastCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(getChildCount() - 1, -1, true, false);
return child == null ? NO_POSITION : getPosition(child);
}
//for loop in findOneVisibleChild method executes once
if (completelyVisible) {
//Item is above RecyclerView height and acceptPartiallyVisible is true,partiallyVisibler is not assigned
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
Only by linking the above four methods with the findOne Visible Child () method can we know the true face of Lushan Mountain and get what we want! Readers can focus on the findOne VisibleChild method according to the annotations.