Skip to content

Commit 7236d32

Browse files
authored
fix(android-animations): reuse animatorSet to prevent high memory usage (#6930)
1 parent 09fa085 commit 7236d32

File tree

3 files changed

+43
-19
lines changed

3 files changed

+43
-19
lines changed

tns-core-modules/ui/animation/animation.android.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from "../styling/style-properties";
1010

1111
import { layout } from "../../utils/utils";
12+
import { device } from "../../platform";
1213
import lazy from "../../utils/lazy";
1314

1415
export * from "./animation-common";
@@ -92,6 +93,7 @@ export class Animation extends AnimationBase {
9293
private _propertyResetCallbacks: Array<Function>;
9394
private _valueSource: "animation" | "keyframe";
9495
private _target: View;
96+
private _resetOnFinish: boolean = true;
9597

9698
constructor(animationDefinitions: Array<AnimationDefinitionInternal>, playSequentially?: boolean) {
9799
super(animationDefinitions, playSequentially);
@@ -134,12 +136,18 @@ export class Animation extends AnimationBase {
134136
});
135137
}
136138

137-
public play(): AnimationPromise {
139+
public play(resetOnFinish?: boolean): AnimationPromise {
140+
if (resetOnFinish !== undefined) {
141+
this._resetOnFinish = resetOnFinish;
142+
}
143+
138144
if (this.isPlaying) {
139145
return this._rejectAlreadyPlaying();
140146
}
141147

142-
let animationFinishedPromise = super.play();
148+
if (this._animatorSet) {
149+
return this._play();
150+
}
143151

144152
this._animators = new Array<android.animation.Animator>();
145153
this._propertyUpdateCallbacks = new Array<Function>();
@@ -156,21 +164,8 @@ export class Animation extends AnimationBase {
156164

157165
this._animatorSet = new android.animation.AnimatorSet();
158166
this._animatorSet.addListener(this._animatorListener);
159-
if (this._animators.length > 0) {
160-
if (this._playSequentially) {
161-
this._animatorSet.playSequentially(this._nativeAnimatorsArray);
162-
}
163-
else {
164-
this._animatorSet.playTogether(this._nativeAnimatorsArray);
165-
}
166-
}
167167

168-
if (traceEnabled()) {
169-
traceWrite("Starting " + this._nativeAnimatorsArray.length + " animations " + (this._playSequentially ? "sequentially." : "together."), traceCategories.Animation);
170-
}
171-
this._animatorSet.setupStartValues();
172-
this._animatorSet.start();
173-
return animationFinishedPromise;
168+
return this._play();
174169
}
175170

176171
public cancel(): void {
@@ -188,6 +183,33 @@ export class Animation extends AnimationBase {
188183
return _resolveAnimationCurve(curve);
189184
}
190185

186+
private _play(): AnimationPromise {
187+
const animationFinishedPromise = super.play();
188+
189+
if (device.sdkVersion <= "23") {
190+
this._animatorSet = new android.animation.AnimatorSet();
191+
this._animatorSet.addListener(this._animatorListener);
192+
}
193+
194+
if (this._animators.length > 0) {
195+
if (this._playSequentially) {
196+
this._animatorSet.playSequentially(this._nativeAnimatorsArray);
197+
}
198+
else {
199+
this._animatorSet.playTogether(this._nativeAnimatorsArray);
200+
}
201+
}
202+
203+
if (traceEnabled()) {
204+
traceWrite("Starting " + this._nativeAnimatorsArray.length + " animations " + (this._playSequentially ? "sequentially." : "together."), traceCategories.Animation);
205+
}
206+
207+
this._animatorSet.setupStartValues();
208+
this._animatorSet.start();
209+
210+
return animationFinishedPromise;
211+
}
212+
191213
private _onAndroidAnimationEnd() { // tslint:disable-line
192214
if (!this.isPlaying) {
193215
// It has been cancelled
@@ -197,7 +219,7 @@ export class Animation extends AnimationBase {
197219
this._propertyUpdateCallbacks.forEach(v => v());
198220
this._resolveAnimationFinishedPromise();
199221

200-
if (this._target) {
222+
if (this._resetOnFinish && this._target) {
201223
this._target._removeAnimation(this);
202224
}
203225
}

tns-core-modules/ui/animation/animation.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export type AnimationPromise = Promise<void> & Cancelable;
126126
*/
127127
export class Animation {
128128
constructor(animationDefinitions: Array<AnimationDefinition>, playSequentially?: boolean);
129-
public play: () => AnimationPromise;
129+
public play: (resetOnFinish?: boolean) => AnimationPromise;
130130
public cancel: () => void;
131131
public isPlaying: boolean;
132132
public _resolveAnimationCurve(curve: any): any;

tns-core-modules/ui/animation/keyframe-animation.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,10 @@ export class KeyframeAnimation implements KeyframeAnimationDefinition {
243243
this._nativeAnimations.push(animation);
244244
}
245245

246+
const isLastIteration = iterations - 1 <= 0;
247+
246248
// Catch the animation cancel to prevent unhandled promise rejection warnings
247-
animation.play().then(() => {
249+
animation.play(isLastIteration).then(() => {
248250
this.animate(view, index + 1, iterations);
249251
}, (error: any) => {
250252
traceWrite(typeof error === "string" ? error : error.message, traceCategories.Animation, traceType.warn);

0 commit comments

Comments
 (0)