Skip to content
This repository has been archived by the owner on Jul 14, 2021. It is now read-only.

Commit

Permalink
关键路径下LayoutHelpers相关性能优化
Browse files Browse the repository at this point in the history
1.LinkedList的高效遍历,复杂度降低一个数量级,在2000+元素个数下无卡顿
2.排序过程简化,复用中间数组
3.二分搜索避免LinkedList的get频繁调用,复用数组根据索引直接定位
  • Loading branch information
littleseven committed Jan 23, 2019
1 parent 1d94f2b commit dd74316
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
* An implement of {@link LayoutHelperFinder} which finds layoutHelpers by position
Expand All @@ -46,6 +49,8 @@ public class RangeLayoutHelperFinder extends LayoutHelperFinder {
@NonNull
private List<LayoutHelper> mReverseLayoutHelpers =new LinkedList<>();

private LayoutHelperItem[] mSortedLayoutHelpers = null;

@NonNull
private Comparator<LayoutHelperItem> mLayoutHelperItemComparator = new Comparator<LayoutHelperItem>() {
@Override
Expand All @@ -68,16 +73,21 @@ public void setLayouts(@Nullable List<LayoutHelper> layouts) {
mReverseLayoutHelpers.clear();
mLayoutHelperItems.clear();
if (layouts != null) {
for (int i = 0, size = layouts.size(); i < size; i++) {
LayoutHelper helper = layouts.get(i);
ListIterator<LayoutHelper> iterator = layouts.listIterator();
LayoutHelper helper = null;
while (iterator.hasNext()) {
helper = iterator.next();
mLayoutHelpers.add(helper);
mLayoutHelperItems.add(new LayoutHelperItem(helper));
}
for (int i = layouts.size() - 1; i >= 0; i--) {
mReverseLayoutHelpers.add(layouts.get(i));

while (iterator.hasPrevious()) {
mReverseLayoutHelpers.add(iterator.previous());
}

Collections.sort(mLayoutHelperItems, mLayoutHelperItemComparator);
// Collections.sort(mLayoutHelperItems, mLayoutHelperItemComparator);
mSortedLayoutHelpers = mLayoutHelperItems.toArray(new LayoutHelperItem[mLayoutHelperItems.size()]);
Arrays.sort(mSortedLayoutHelpers, mLayoutHelperItemComparator);
}
}

Expand All @@ -90,18 +100,17 @@ protected List<LayoutHelper> getLayoutHelpers() {
@Nullable
@Override
public LayoutHelper getLayoutHelper(int position) {
final int count = mLayoutHelperItems.size();
if (count == 0) {
if (mSortedLayoutHelpers == null || mSortedLayoutHelpers.length == 0) {
return null;
}
final int count = mSortedLayoutHelpers.length;

int s = 0, e = count - 1, m;
LayoutHelperItem rs = null;

// binary search range
while (s <= e) {
m = (s + e) / 2;
rs = mLayoutHelperItems.get(m);
rs = mSortedLayoutHelpers[m];
if (rs.getStartPosition() > position) {
e = m - 1;
} else if (rs.getEndPosition() < position) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@
import android.view.ViewGroup;
import android.view.ViewParent;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;


Expand Down Expand Up @@ -107,6 +109,20 @@ public static void enableDebugging(boolean isDebug) {

private ViewLifeCycleHelper mViewLifeCycleHelper;

private Comparator<Pair<Range<Integer>, Integer>> mRangeComparator = new Comparator<Pair<Range<Integer>, Integer>>() {
@Override
public int compare(Pair<Range<Integer>, Integer> a, Pair<Range<Integer>, Integer> b) {
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;

Range<Integer> lr = a.first;
Range<Integer> rr = b.first;

return lr.getLower() - rr.getLower();
}
};

public VirtualLayoutManager(@NonNull final Context context) {
this(context, VERTICAL);
}
Expand Down Expand Up @@ -175,9 +191,12 @@ public void setHelperFinder(@NonNull final LayoutHelperFinder finder) {
List<LayoutHelper> helpers = new LinkedList<>();
if (this.mHelperFinder != null) {
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper helper = layoutHelpers.get(i);
helpers.add(helper);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
helpers.add(layoutHelper);

}
}

Expand Down Expand Up @@ -211,17 +230,18 @@ public void setFixOffset(int left, int top, int right, int bottom) {
*/
public void setLayoutHelpers(@Nullable List<LayoutHelper> helpers) {
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper helper = layoutHelpers.get(i);
Iterator<LayoutHelper> it0 = layoutHelpers.iterator();
while (it0.hasNext()) {
LayoutHelper helper = it0.next();
oldHelpersSet.put(System.identityHashCode(helper), helper);
}

// set ranges
if (helpers != null) {
int start = 0;
for (int i = 0; i < helpers.size(); i++) {
LayoutHelper helper = helpers.get(i);

Iterator<LayoutHelper> it1 = helpers.iterator();
while (it1.hasNext()) {
LayoutHelper helper = it1.next();
if (helper instanceof FixAreaLayoutHelper) {
((FixAreaLayoutHelper) helper).setAdjuster(mFixAreaAdjustor);
}
Expand All @@ -244,12 +264,12 @@ public void setLayoutHelpers(@Nullable List<LayoutHelper> helpers) {
this.mHelperFinder.setLayouts(helpers);

layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper helper = layoutHelpers.get(i);
newHelpersSet.put(System.identityHashCode(helper), helper);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
while (iterator.hasNext()) {
LayoutHelper layoutHelper = iterator.next();
newHelpersSet.put(System.identityHashCode(layoutHelper), layoutHelper);
}


for (Iterator<Map.Entry<Integer, LayoutHelper>> it = oldHelpersSet.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<Integer, LayoutHelper> entry = it.next();
Integer key = entry.getKey();
Expand Down Expand Up @@ -364,8 +384,10 @@ public void onAnchorReady(RecyclerView.State state, ExposeLinearLayoutManagerEx.
mTempAnchorInfoWrapper.position = anchorInfo.mPosition;
mTempAnchorInfoWrapper.coordinate = anchorInfo.mCoordinate;
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.onRefreshLayout(state, mTempAnchorInfoWrapper, this);
}
}
Expand Down Expand Up @@ -434,8 +456,10 @@ private void runPreLayout(RecyclerView.Recycler recycler, RecyclerView.State sta

if (mNested == 0) {
List<LayoutHelper> reverseLayoutHelpers = mHelperFinder.reverse();
for (int i = 0, size = reverseLayoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = reverseLayoutHelpers.get(i);
Iterator<LayoutHelper> iterator = reverseLayoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.beforeLayout(recycler, state, this);
}
}
Expand All @@ -450,8 +474,10 @@ private void runPostLayout(RecyclerView.Recycler recycler, RecyclerView.State st
final int startPosition = findFirstVisibleItemPosition();
final int endPosition = findLastVisibleItemPosition();
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
try {
layoutHelper.afterLayout(recycler, state, startPosition, endPosition, scrolled, this);
} catch (Exception e) {
Expand Down Expand Up @@ -608,8 +634,10 @@ public void onScrollStateChanged(int state) {
int startPosition = findFirstVisibleItemPosition();
int endPosition = findLastVisibleItemPosition();
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.onScrollStateChanged(state, startPosition, endPosition, this);
}
}
Expand All @@ -619,18 +647,23 @@ public void offsetChildrenHorizontal(int dx) {
super.offsetChildrenHorizontal(dx);

List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.onOffsetChildrenHorizontal(dx, this);

}
}

@Override
public void offsetChildrenVertical(int dy) {
super.offsetChildrenVertical(dy);
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.onOffsetChildrenVertical(dy, this);
}

Expand All @@ -657,7 +690,7 @@ public int getVirtualLayoutDirection() {

private LayoutStateWrapper mTempLayoutStateWrapper = new LayoutStateWrapper();

private List<Pair<Range<Integer>, Integer>> mRangeLengths = new LinkedList<>();
private List<Pair<Range<Integer>, Integer>> mRangeLengths = new ArrayList<>();

@Nullable
private int findRangeLength(@NonNull final Range<Integer> range) {
Expand Down Expand Up @@ -732,19 +765,7 @@ protected void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State st
}

mRangeLengths.add(Pair.create(range, consumed));
Collections.sort(mRangeLengths, new Comparator<Pair<Range<Integer>, Integer>>() {
@Override
public int compare(Pair<Range<Integer>, Integer> a, Pair<Range<Integer>, Integer> b) {
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;

Range<Integer> lr = a.first;
Range<Integer> rr = b.first;

return lr.getLower() - rr.getLower();
}
});
Collections.sort(mRangeLengths, mRangeComparator);
}
}

Expand Down Expand Up @@ -852,8 +873,10 @@ public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCo
@Override
public void onItemsChanged(RecyclerView recyclerView) {
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.onItemsChanged(this);
}

Expand Down Expand Up @@ -907,8 +930,10 @@ public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycl
super.onDetachedFromWindow(view, recycler);

List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
layoutHelper.clear(this);
}

Expand Down Expand Up @@ -1141,8 +1166,10 @@ public List<View> getFixedViews() {
// TODO: support zIndex?
List<View> views = new LinkedList<>();
List<LayoutHelper> layoutHelpers = mHelperFinder.getLayoutHelpers();
for (int i = 0, size = layoutHelpers.size(); i < size; i++) {
LayoutHelper layoutHelper = layoutHelpers.get(i);
Iterator<LayoutHelper> iterator = layoutHelpers.iterator();
LayoutHelper layoutHelper = null;
while (iterator.hasNext()) {
layoutHelper = iterator.next();
View fixedView = layoutHelper.getFixedView();
if (fixedView != null) {
views.add(fixedView);
Expand Down

0 comments on commit dd74316

Please sign in to comment.