带有动画的 onBackPressed 中的内存泄漏
MemoryLeak in onBackPressed with Animation
我在一个开源应用程序中创建了一个相当复杂的结束动画。
如果调用 onBackPressed() 方法,应用程序将为视图设置动画并关闭。好像有内存韭菜,因为之后它不会停止分配新的ram。如果我删除动画并只调用普通的 onBackPressed 我没有提到的行为。
这是我在 onBackPressed 方法中调用的代码:
//make global var :D
ViewPropertyAnimator hideFabAnimator;
@Override
public void onBackPressed() {
mFabDownloadButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
//move the share fab below the normal fab (58 because this is the margin top + the half
mFabShareButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
//create the fab animation and hide fabProgress animation, set an delay so those will hide after the shareFab is below the main fab
hideFabAnimator = Utils.hideViewByScaleXY(mFabButton)
.setDuration(ANIMATION_DURATION_MEDIUM);
Utils.hideViewByScaleXY(mFabDownloadButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
Utils.hideViewByScaleXY(mFabShareButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
Utils.hideViewByScaleXY(mFabProgress)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
//add listener so we can react after the animation is finished
hideFabAnimator.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
try {
ViewPropertyAnimator hideFabAnimator = Utils.hideViewByScaleY(mTitleContainer);
hideFabAnimator.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
coolBack()
}
});
} catch (Exception ex) {
super.onAnimationEnd(animation);
coolBack()
}
}
});
hideFabAnimator.start();
super.onAnimationEnd(animation);
}
})
.start();
}
/**
*
*/
private void coolBack() {
try {
super.onBackPressed();
} catch (Exception e) {
}
}
您可以在此处找到相同的来源@github:https://github.com/mikepenz/wall-splash-android/blob/master/app/src/main/java/com/mikepenz/unsplash/activities/DetailActivity.java#L701
我已经尝试了很多不同的东西。但没有任何帮助。
谢谢。
所以我能够解决这个问题。似乎如果你使用没有 animationListener 的普通动画,它可能会发生(它会发生)动画无法完成并将保持 "in-tact"。所以它似乎仍在后台处理某些东西,即使 activity 已经关闭。
所以我能够通过定义一个侦听器来解决这个问题-"chain" 并检查我的所有动画是否完成。
这是有效的代码:
@Override
public void onBackPressed() {
mFabDownloadButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener1)
.start();
//move the share fab below the normal fab (58 because this is the margin top + the half
mFabShareButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener1)
.start();
}
private CustomAnimatorListener animationFinishListener1 = new CustomAnimatorListener() {
private int animateFinish1 = 0;
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
process();
}
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
process();
}
private void process() {
animateFinish1 = animateFinish1 + 1;
if (animateFinish1 == 2) {
//create the fab animation and hide fabProgress animation, set an delay so those will hide after the shareFab is below the main fab
Utils.hideViewByScaleXY(mFabDownloadButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
Utils.hideViewByScaleXY(mFabShareButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
Utils.hideViewByScaleXY(mFabProgress)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
Utils.hideViewByScaleXY(mFabButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
}
}
};
private CustomAnimatorListener animationFinishListener2 = new CustomAnimatorListener() {
private int animateFinish2 = 0;
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
process();
}
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
process();
}
private void process() {
animateFinish2 = animateFinish2 + 1;
if (animateFinish2 == 4) {
ViewPropertyAnimator hideFabAnimator = Utils.hideViewByScaleY(mTitleContainer);
hideFabAnimator.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
coolBack();
}
});
}
}
};
/**
*
*/
private void coolBack() {
try {
super.onBackPressed();
} catch (Exception e) {
// ew;
}
}
所以我对我的动画进行计数,只有在第一个 "batch" 个动画完成后才会转到下一个动画,然后我将继续第二个 "batch"动画。一旦这些完成,我将完成 activity。
我有一个类似的动画泄漏。在我的例子中,我使用了
scaleY.setRepeatCount(1);
scaleY.setRepeatMode(ValueAnimator.REVERSE);
对于 setRepeatCount,我之前使用了 INFINITY,它也从不结束动画,即使在调用显式 cancle() 或 end() 之后也没有。我只是将它更改为 1(它不再是无穷大,但我可以接受)。
刚刚添加了这个答案,以防有人 运行 也加入其中。
我在一个开源应用程序中创建了一个相当复杂的结束动画。
如果调用 onBackPressed() 方法,应用程序将为视图设置动画并关闭。好像有内存韭菜,因为之后它不会停止分配新的ram。如果我删除动画并只调用普通的 onBackPressed 我没有提到的行为。
这是我在 onBackPressed 方法中调用的代码:
//make global var :D
ViewPropertyAnimator hideFabAnimator;
@Override
public void onBackPressed() {
mFabDownloadButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
//move the share fab below the normal fab (58 because this is the margin top + the half
mFabShareButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
//create the fab animation and hide fabProgress animation, set an delay so those will hide after the shareFab is below the main fab
hideFabAnimator = Utils.hideViewByScaleXY(mFabButton)
.setDuration(ANIMATION_DURATION_MEDIUM);
Utils.hideViewByScaleXY(mFabDownloadButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
Utils.hideViewByScaleXY(mFabShareButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
Utils.hideViewByScaleXY(mFabProgress)
.setDuration(ANIMATION_DURATION_MEDIUM)
.start();
//add listener so we can react after the animation is finished
hideFabAnimator.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
try {
ViewPropertyAnimator hideFabAnimator = Utils.hideViewByScaleY(mTitleContainer);
hideFabAnimator.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
coolBack()
}
});
} catch (Exception ex) {
super.onAnimationEnd(animation);
coolBack()
}
}
});
hideFabAnimator.start();
super.onAnimationEnd(animation);
}
})
.start();
}
/**
*
*/
private void coolBack() {
try {
super.onBackPressed();
} catch (Exception e) {
}
}
您可以在此处找到相同的来源@github:https://github.com/mikepenz/wall-splash-android/blob/master/app/src/main/java/com/mikepenz/unsplash/activities/DetailActivity.java#L701
我已经尝试了很多不同的东西。但没有任何帮助。
谢谢。
所以我能够解决这个问题。似乎如果你使用没有 animationListener 的普通动画,它可能会发生(它会发生)动画无法完成并将保持 "in-tact"。所以它似乎仍在后台处理某些东西,即使 activity 已经关闭。
所以我能够通过定义一个侦听器来解决这个问题-"chain" 并检查我的所有动画是否完成。
这是有效的代码:
@Override
public void onBackPressed() {
mFabDownloadButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener1)
.start();
//move the share fab below the normal fab (58 because this is the margin top + the half
mFabShareButton.animate()
.translationX(0)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener1)
.start();
}
private CustomAnimatorListener animationFinishListener1 = new CustomAnimatorListener() {
private int animateFinish1 = 0;
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
process();
}
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
process();
}
private void process() {
animateFinish1 = animateFinish1 + 1;
if (animateFinish1 == 2) {
//create the fab animation and hide fabProgress animation, set an delay so those will hide after the shareFab is below the main fab
Utils.hideViewByScaleXY(mFabDownloadButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
Utils.hideViewByScaleXY(mFabShareButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
Utils.hideViewByScaleXY(mFabProgress)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
Utils.hideViewByScaleXY(mFabButton)
.setDuration(ANIMATION_DURATION_MEDIUM)
.setListener(animationFinishListener2)
.start();
}
}
};
private CustomAnimatorListener animationFinishListener2 = new CustomAnimatorListener() {
private int animateFinish2 = 0;
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
process();
}
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
process();
}
private void process() {
animateFinish2 = animateFinish2 + 1;
if (animateFinish2 == 4) {
ViewPropertyAnimator hideFabAnimator = Utils.hideViewByScaleY(mTitleContainer);
hideFabAnimator.setListener(new CustomAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
coolBack();
}
});
}
}
};
/**
*
*/
private void coolBack() {
try {
super.onBackPressed();
} catch (Exception e) {
// ew;
}
}
所以我对我的动画进行计数,只有在第一个 "batch" 个动画完成后才会转到下一个动画,然后我将继续第二个 "batch"动画。一旦这些完成,我将完成 activity。
我有一个类似的动画泄漏。在我的例子中,我使用了
scaleY.setRepeatCount(1);
scaleY.setRepeatMode(ValueAnimator.REVERSE);
对于 setRepeatCount,我之前使用了 INFINITY,它也从不结束动画,即使在调用显式 cancle() 或 end() 之后也没有。我只是将它更改为 1(它不再是无穷大,但我可以接受)。 刚刚添加了这个答案,以防有人 运行 也加入其中。