Skip to content

Commit cc550d7

Browse files
committed
fix: a bunch of fixes to make collectionview faster
1 parent 7bc0498 commit cc550d7

File tree

5 files changed

+206
-144
lines changed

5 files changed

+206
-144
lines changed

packages/collectionview/platforms/android/java/com/nativescript/collectionview/RecyclerView.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
import android.view.ViewGroup;
66
import android.util.Log;
77
import androidx.recyclerview.widget.LinearSmoothScroller;
8+
import jp.wasabeef.recyclerview.animators.FadeInAnimator;
9+
import jp.wasabeef.recyclerview.animators.BaseItemAnimator;
10+
import android.view.animation.OvershootInterpolator;
811

912
public class RecyclerView extends androidx.recyclerview.widget.RecyclerView {
1013
static final String TAG = "RecyclerView";
1114
public SizeChangedListener sizeChangedListener = null;
1215
protected com.nativescript.collectionview.SmoothScroller smoothScroller;
16+
public FadeInAnimator animator;
1317
public RecyclerView(Context context) {
1418
this(context, null);
1519
}
@@ -21,6 +25,15 @@ public RecyclerView(Context context, android.util.AttributeSet attrs) {
2125
setHasFixedSize(true);
2226
setFocusable(true);
2327
setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
28+
29+
30+
animator = new FadeInAnimator();
31+
// animator.setInterpolator(new OvershootInterpolator());
32+
animator.setMoveDuration(200);
33+
setItemAnimator(animator);
34+
// Change animations are enabled by default since support-v7-recyclerview v22.
35+
// Need to disable them when using animation indicator.
36+
// animator.setSupportsChangeAnimations(false);
2437
}
2538

2639
static public RecyclerView createRecyclerView(Context context) {
@@ -46,7 +59,14 @@ protected void onMeasure(int widthMeasureSpec,
4659
sizeChangedListener.onMeasure();
4760
}
4861
}
49-
62+
@Override
63+
protected void onLayout(boolean changed, int l, int t, int r, int b) {
64+
super.onLayout(changed, l, t, r, b);
65+
if (sizeChangedListener != null) {
66+
sizeChangedListener.onLayout(changed, l, t, r, b);
67+
}
68+
}
69+
5070
@Override
5171
public void smoothScrollToPosition(int position) {
5272
this.smoothScrollToPosition(position, LinearSmoothScroller.SNAP_TO_START);
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.nativescript.collectionview;
22

33
public interface SizeChangedListener {
4-
public void onSizeChanged(int w, int h, int oldw, int oldh);
4+
// public void onSizeChanged(int w, int h, int oldw, int oldh);
5+
public void onLayout(boolean changed, int l, int t, int r, int b);
56
public void onMeasure();
67
}

src/collectionview/index-common.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,13 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
178178
public abstract scrollToOffset(value: number, animated?: boolean): any;
179179

180180
protected updateInnerSize() {
181+
const lastInnerWidth = this._innerWidth;
182+
const lastInnerHeight = this._innerHeight;
181183
const width = this.getMeasuredWidth();
182184
const height = this.getMeasuredHeight();
185+
if (width === 0 || height === 0) {
186+
return false;
187+
}
183188
this._innerWidth = width - this.effectivePaddingLeft - this.effectivePaddingRight;
184189
if (this.colWidth) {
185190
let newValue = toDevicePixels(this.colWidth, autoEffectiveColWidth, this._innerWidth); // We cannot use 0 for auto as it throws for android.
@@ -201,6 +206,7 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
201206
this._effectiveRowHeight = newValue;
202207
}
203208
}
209+
return lastInnerWidth !== this._innerWidth || lastInnerHeight !== this._innerHeight;
204210
}
205211
// public onLayout(left: number, top: number, right: number, bottom: number) {
206212
// super.onLayout(left, top, right, bottom);
@@ -389,6 +395,7 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
389395
private _itemTemplateSelectorBindable;
390396
_itemTemplateSelector: Function;
391397
onItemTemplateSelectorChanged(oldValue, newValue) {
398+
const start = Date.now()
392399
if (typeof newValue === 'string') {
393400
if (!this._itemTemplateSelectorBindable) {
394401
this._itemTemplateSelectorBindable = new ProxyViewContainer();
@@ -410,7 +417,10 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
410417
private _itemIdGeneratorBindable;
411418
// public _itemIdGenerator: (item: any, index: number, items: any) => number = (_item: any, index: number) => index;
412419
public _itemIdGenerator: (item: any, index: number, items: any) => number = null;
420+
421+
@profile
413422
onItemIdGeneratorChanged(oldValue, newValue) {
423+
const start = Date.now()
414424
if (typeof newValue === 'string') {
415425
if (!this._itemIdGeneratorBindable) {
416426
this._itemIdGeneratorBindable = new ProxyViewContainer();
@@ -445,7 +455,10 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
445455
this.onTemplateRemoved(key);
446456
}
447457
}
458+
459+
@profile
448460
onItemTemplatesChanged(oldValue, newValue) {
461+
const start = Date.now()
449462
this._itemTemplatesInternal = new Map();
450463
if (newValue) {
451464
newValue.forEach((t) => {
@@ -471,7 +484,9 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
471484
getItemArrayAtIndex(index: number) {
472485
return this.items[index];
473486
}
487+
@profile
474488
onItemsChanged(oldValue, newValue) {
489+
const start = Date.now()
475490
const getItem = newValue && (newValue as ItemsSource).getItem;
476491
this.isItemsSourceIn = typeof getItem === 'function';
477492
// we override the method to prevent the test on every getItem
@@ -485,18 +500,9 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
485500
}
486501
this.refresh();
487502
}
488-
489-
onItemTemplatesPropertyChanged(oldValue, newValue) {
490-
this.onItemTemplatesChanged(oldValue, newValue);
491-
}
492-
onItemTemplatePropertyChanged(oldValue, newValue) {
493-
this.onItemTemplateChanged(oldValue, newValue);
494-
}
495-
onItemsChangedInternal = (oldValue, newValue) => {
496-
this.onItemsChanged(oldValue, newValue);
497-
};
498503
spanSize: (item, index: number) => number;
499-
onSpanSizeChangedInternal = (oldValue, newValue) => {
504+
onSpanSizeChanged = (oldValue, newValue) => {
505+
const start = Date.now()
500506
this.spanSize = newValue;
501507
this.refresh();
502508
};
@@ -507,9 +513,11 @@ export abstract class CollectionViewBase extends View implements CollectionViewD
507513
this.refresh();
508514
}
509515
}
516+
@profile
510517
onSourceCollectionChanged(event: ChangedData<any>) {
511518
this.refresh();
512519
}
520+
@profile
513521
onSourceCollectionChangedInternal(event: ChangedData<any>) {
514522
if (this._dataUpdatesSuspended === false) {
515523
this.onSourceCollectionChanged(event);
@@ -602,8 +610,10 @@ export const rowHeightProperty = new Property<CollectionViewBase, CoreTypes.Perc
602610
equalityComparer: PercentLength.equals,
603611
valueConverter: PercentLength.parse,
604612
valueChanged: (target, oldValue, newValue) => {
605-
target._effectiveRowHeight = PercentLength.toDevicePixels(newValue, autoEffectiveRowHeight, target._innerHeight);
606-
target._onRowHeightPropertyChanged(oldValue, newValue);
613+
if (target._innerHeight !== 0) {
614+
target._effectiveRowHeight = PercentLength.toDevicePixels(newValue, autoEffectiveRowHeight, target._innerHeight);
615+
target._onRowHeightPropertyChanged(oldValue, newValue);
616+
}
607617
}
608618
});
609619
rowHeightProperty.register(CollectionViewBase);
@@ -617,8 +627,8 @@ export const colWidthProperty = new Property<CollectionViewBase, CoreTypes.Perce
617627
valueChanged: (target, oldValue, newValue) => {
618628
if (target._innerWidth !== 0) {
619629
target._effectiveColWidth = PercentLength.toDevicePixels(newValue, autoEffectiveColWidth, target._innerWidth);
630+
target._onColWidthPropertyChanged(oldValue, newValue);
620631
}
621-
target._onColWidthPropertyChanged(oldValue, newValue);
622632
}
623633
});
624634
colWidthProperty.register(CollectionViewBase);
@@ -638,7 +648,7 @@ orientationProperty.register(CollectionViewBase);
638648
export const itemTemplateProperty = new Property<CollectionViewBase, string | Template>({
639649
name: 'itemTemplate',
640650
valueChanged(target, oldValue, newValue) {
641-
target.onItemTemplatePropertyChanged(oldValue, newValue);
651+
target.onItemTemplateChanged(oldValue, newValue);
642652
}
643653
});
644654
itemTemplateProperty.register(CollectionViewBase);
@@ -653,7 +663,7 @@ export const itemTemplatesProperty = new Property<CollectionViewBase, KeyedTempl
653663
return value;
654664
},
655665
valueChanged(target, oldValue, newValue) {
656-
target.onItemTemplatesPropertyChanged(oldValue, newValue);
666+
target.onItemTemplatesChanged(oldValue, newValue);
657667
}
658668
});
659669
itemTemplatesProperty.register(CollectionViewBase);
@@ -679,7 +689,7 @@ export const itemsProperty = new Property<CollectionViewBase, Function>({
679689
name: 'items',
680690
defaultValue: undefined,
681691
valueChanged(target, oldValue, newValue) {
682-
target.onItemsChangedInternal(oldValue, newValue);
692+
target.onItemsChanged(oldValue, newValue);
683693
}
684694
});
685695
itemsProperty.register(CollectionViewBase);
@@ -688,7 +698,7 @@ export const spanSizeProperty = new Property<CollectionViewBase, Function>({
688698
name: 'spanSize',
689699
defaultValue: undefined,
690700
valueChanged(target, oldValue, newValue) {
691-
target.onSpanSizeChangedInternal(oldValue, newValue);
701+
target.onSpanSizeChanged(oldValue, newValue);
692702
}
693703
});
694704
spanSizeProperty.register(CollectionViewBase);

0 commit comments

Comments
 (0)