0

Я создал довольно сложную анимацию конца в приложении с открытым исходным кодом.MemoryLeak in onBackPressed with Animation

Если метод onBackPressed() называется приложением, он будет анимировать представления и закрыть. кажется, что есть лук-покров памяти, потому что он не перестанет выделять новый баран после этого. Если я удалю анимацию и просто вызову обычный 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

Я пытался уже много разных вещей. но ничего не помогло.

Спасибо.

+0

попробуйте удаление super.onBackPressed() .. использование отделка() сверху анимация конец –

+0

oh извините. полностью пропустил эту линию. была одной из вещей, которые я пробовал. подождите, я обновляю свой вопрос. – mikepenz

ответ

0

Так что я смог решить эту проблему. Кажется, что если вы используете обычные анимации без аниматора, может случиться (что произойдет), что анимация не может закончить и останется «в-такте». Похоже, что он все еще обрабатывает что-то в фоновом режиме, даже если активность уже закрыта.

Так что я смог обойти эту проблему, определив цепочку прослушивателей и проверив, что все мои анимации закончены.

Вот код, который работает:

@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; 
    } 
} 

Так я держать количество моей анимации, и будет идти только на следующую анимацию, если первая «партия» анимация завершена, и после этого я буду продолжайте вторую «партию» анимаций. Как только они закончатся, я закончу работу.

0

У меня была простая утечка с анимацией. В моем случае я использовал

scaleY.setRepeatCount(1); 
scaleY.setRepeatMode(ValueAnimator.REVERSE); 

для setRepeatCount я использовал INFINITY до того, что также не endet анимации, даже после вызова явного CANCLE() или конца(). Я просто изменил его на 1 (его не бесконечность больше, но я могу жить с ним). Только что добавил этот ответ, если кто-то столкнется с этим.