Skip to content

Commit c5f55ff

Browse files
committed
fix(android): reduce the number of refresh calls a collectionview goes through on start
1 parent 3457cc1 commit c5f55ff

File tree

6 files changed

+47
-20
lines changed

6 files changed

+47
-20
lines changed

demo-snippets/vue3/install.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export function installPlugin(app: any) {
1919
app.use(SwipeMenuPlugin);
2020
install();
2121
}
22-
2322
export const demos = [
2423
{ name: 'Card', path: 'card', component: CardHome },
2524
{ name: 'Simple Grid', path: 'simple-grid', component: SimpleGrid },

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ protected void onMeasure(int widthMeasureSpec,
5858
int heightMeasureSpec) {
5959
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
6060
if (sizeChangedListener != null) {
61-
sizeChangedListener.onMeasure();
61+
sizeChangedListener.onMeasure(widthMeasureSpec, heightMeasureSpec);
6262
}
6363
}
6464
@Override

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
public interface SizeChangedListener {
44
// public void onSizeChanged(int w, int h, int oldw, int oldh);
55
public void onLayout(boolean changed, int l, int t, int r, int b);
6-
public void onMeasure();
6+
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec);
77
}

src/collectionview/index-common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export namespace knownMultiTemplates {
6868

6969
export interface Plugin {
7070
onLayout?: Function;
71+
onMeasure?: Function;
7172
}
7273

7374
function toDevicePixels(length: CoreTypes.PercentLengthType, auto: number = Number.NaN, parentAvailableWidth: number = Number.NaN): number {

src/collectionview/index.android.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ export class CollectionView extends CollectionViewBase {
277277

278278
nativeView.sizeChangedListener = new com.nativescript.collectionview.SizeChangedListener({
279279
onLayout:(changed, left, top, right, bottom) => changed && this.onLayout(left, top, right, bottom),
280-
onMeasure: () => this.updateInnerSize()
280+
onMeasure: (widthMeasureSpec, heightMeasureSpec) => this.onMeasure(widthMeasureSpec, heightMeasureSpec)
281281
});
282282
this.spanSize = this._getSpanSize;
283283

@@ -289,9 +289,9 @@ export class CollectionView extends CollectionViewBase {
289289
// animator.setSupportsChangeAnimations(false);
290290

291291
// nativeView.setItemAnimator(animator);
292-
// (nativeView.getItemAnimator() ).setSupportsChangeAnimations(false);
293292

294-
this.refresh();
293+
// enforce the first refresh for the collectionview to be ready as soon as possible
294+
this.refresh(true);
295295
}
296296
@profile
297297
public disposeNativeView() {
@@ -739,7 +739,7 @@ export class CollectionView extends CollectionViewBase {
739739
updateSpanCount(requestLayout = true) {
740740
if (this.mInPropertiesSet) {
741741
this.mShouldUpdateSpanCount = true;
742-
return;
742+
return false;
743743
}
744744
this.mShouldUpdateSpanCount = false;
745745
const layoutManager = this.layoutManager;
@@ -767,6 +767,13 @@ export class CollectionView extends CollectionViewBase {
767767
if (result) {
768768
this.updateSpanCount();
769769
}
770+
// there is no need to call refresh if it was triggered before with same size.
771+
// this refresh is just to handle size change
772+
const layoutKey = this._innerWidth + '_' + this._innerHeight;
773+
if (this._isDataDirty || (this._lastLayoutKey && this._lastLayoutKey !== layoutKey)) {
774+
// setTimeout(() => this.refresh(false), 0);
775+
}
776+
this._lastLayoutKey = layoutKey;
770777
return result;
771778
}
772779
@profile
@@ -791,13 +798,33 @@ export class CollectionView extends CollectionViewBase {
791798
const p = CollectionViewBase.plugins[k];
792799
p.onLayout && p.onLayout(this, left, top, right, bottom);
793800
});
794-
// there is no need to call refresh if it was triggered before with same size.
795-
// this refresh is just to handle size change
796-
const layoutKey = this._innerWidth + '_' + this._innerHeight;
797-
if (this._isDataDirty || (this._lastLayoutKey && this._lastLayoutKey !== layoutKey)) {
798-
setTimeout(() => this.refresh(false), 0);
801+
802+
}
803+
@profile
804+
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) {
805+
const lastLayoutKey = this._lastLayoutKey
806+
this.updateInnerSize();
807+
808+
if (lastLayoutKey !== this._lastLayoutKey) {
809+
//we need to refresh visible cells so that they measure to the new size
810+
// for some reason it gets animated even with setSupportsChangeAnimations(false)
811+
// so we clear until it is done
812+
const nativeView = this.nativeViewProtected;
813+
const animator = nativeView.getItemAnimator()
814+
nativeView.setItemAnimator(null);
815+
this.refreshVisibleItems()
816+
setTimeout(() => {
817+
nativeView.setItemAnimator(animator);
818+
}, 0);
799819
}
800-
this._lastLayoutKey = layoutKey;
820+
const p = CollectionViewBase.plugins[this.layoutStyle];
821+
if (p && p.onMeasure) {
822+
p.onMeasure(this, widthMeasureSpec,heightMeasureSpec);
823+
}
824+
this.plugins.forEach((k) => {
825+
const p = CollectionViewBase.plugins[k];
826+
p.onMeasure && p.onMeasure(this, widthMeasureSpec,heightMeasureSpec);
827+
});
801828
}
802829
public onSourceCollectionChanged(event: ChangedData<any>) {
803830
if (!this._listViewAdapter || this._dataUpdatesSuspended) {
@@ -904,7 +931,7 @@ export class CollectionView extends CollectionViewBase {
904931

905932
_layedOut = false;
906933
@profile
907-
public refresh(updateSpanCountRequestsLayout = true) {
934+
public refresh(forceRefresh = false, updateSpanCountRequestsLayout = false) {
908935
if (this.mInPropertiesSet) {
909936
this.mShouldRefresh = true;
910937
return;
@@ -916,10 +943,10 @@ export class CollectionView extends CollectionViewBase {
916943
}
917944
// seems like we refresh sooner
918945
// not sure why it was needed before and not now.
919-
// if (!this.isLoaded || this._innerWidth === 0 || this._innerHeight === 0) {
920-
// this._isDataDirty = true;
921-
// return;
922-
// }
946+
if (!forceRefresh && (!this.isLoaded || !this.nativeView)) {
947+
this._isDataDirty = true;
948+
return;
949+
}
923950
this._isDataDirty = false;
924951
this._lastLayoutKey = this._innerWidth + '_' + this._innerHeight;
925952
let adapter = this._listViewAdapter;

src/collectionview/typings/android.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ declare namespace com {
4949
smoothScrollToPosition(position: number, snapPosition?: number);
5050
}
5151
export class SizeChangedListener {
52-
constructor(impl?: { onLayout(changed:boolean, l: number, t: number, r: number, b: number); onMeasure() });
52+
constructor(impl?: { onLayout(changed:boolean, l: number, t: number, r: number, b: number); onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) });
5353
onLayout(changed:boolean, l: number, t: number, r: number, b: number);
54-
onMeasure();
54+
onMeasure(widthMeasureSpec: number, heightMeasureSpec: number);
5555
}
5656
export class OnScrollListener extends androidx.recyclerview.widget.RecyclerView.OnScrollListener {
5757
constructor(listener: OnScrollListener.Listener);

0 commit comments

Comments
 (0)