java - 动画导致垃圾收集器创建日志条目

标签 java android animation garbage-collection android-animation


我正在使用 TabActivity,其中每个选项卡都是一个 View 。 我想在更改选项卡时创建滑动动画。 每次动画启动时,logcat 都会给出一个 GC 条目:

08-17 16:37:00.840: D/dalvikvm(2767): GC_CONCURRENT freed 1920K, 43% free 6852K/11975K, paused 12ms+14ms, total 72ms
08-17 16:37:01.235: D/dalvikvm(2767): GC_CONCURRENT freed 1480K, 40% free 7215K/11975K, paused 2ms+3ms, total 46ms
08-17 16:37:01.235: D/dalvikvm(2767): WAIT_FOR_CONCURRENT_GC blocked 18ms
08-17 16:37:05.715: D/dalvikvm(2767): GC_CONCURRENT freed 2092K, 43% free 6882K/11975K, paused 12ms+28ms, total 104ms
08-17 16:37:06.370: D/dalvikvm(2767): GC_CONCURRENT freed 779K, 34% free 7912K/11975K, paused 14ms+6ms, total 65ms
08-17 16:37:09.825: D/dalvikvm(2767): GC_FOR_ALLOC freed 1464K, 47% free 6455K/11975K, paused 19ms, total 19ms
08-17 16:37:09.865: D/dalvikvm(2767): GC_FOR_ALLOC freed 1K, 34% free 7988K/11975K, paused 19ms, total 19ms
08-17 16:37:09.865: I/dalvikvm-heap(2767): Grow heap (frag case) to 16.811MB for 944656-byte allocation
08-17 16:37:10.370: D/dalvikvm(2767): GC_CONCURRENT freed 1427K, 38% free 8706K/13959K, paused 2ms+5ms, total 41ms

每次单击选项卡时,都会有两种动画:一种用于当前选项卡滑出,一种用于新选项卡滑入。

这些是动画定义:

public Animation inFromRightAnimation() {
    Animation inFromRight = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT, +1.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f);
    inFromRight.setDuration(500);
    return inFromRight;
}

public Animation outToLeftAnimation() {
    Animation outtoLeft = new TranslateAnimation(
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, -1.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f,
            Animation.RELATIVE_TO_PARENT, 0.0f);
    outtoLeft.setDuration(500);
    return outtoLeft;
}

编辑:这是选项卡更改的代码:( currentTab 是私有(private) int 类成员)

public void onTabChanged(String tabId) {
    if (!initializatorFinished) {
        getTabHost().setCurrentTab(currentTab);
        return;
    }
    tab1 = (LinearLayout) findViewById(R.id.tabHome);
    tab2 = (LinearLayout) findViewById(R.id.tabChanges);
    tab3 = (LinearLayout) findViewById(R.id.tabTests);
    tab4 = (ScrollView) findViewById(R.id.tabSettings);
    tab5 = (LinearLayout) findViewById(R.id.tabInfo);
    int currentTab = GetCurrentTab();
    int newTab = Integer.parseInt(tabId);
        if (currentTab == 1 || currentTab == 0) {
            if (newTab == 2) {
                tab1.setAnimation(outToLeftAnimation());
                tab2.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 4) {
                tab1.setAnimation(outToLeftAnimation());
                tab4.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 5) {
                tab1.setAnimation(outToLeftAnimation());
                tab5.setAnimation(inFromRightAnimation());
            }
        }
        else if (currentTab == 2) {
            if (newTab == 1) {
                tab2.setAnimation(outToLeftAnimation());
                tab1.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 4) {
                tab2.setAnimation(outToLeftAnimation());
                tab4.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 5) {
                tab2.setAnimation(outToLeftAnimation());
                tab5.setAnimation(inFromRightAnimation());
            }
        }
        else if (currentTab == 4) {
            if (newTab == 1) {
                tab4.setAnimation(outToLeftAnimation());
                tab1.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 2) {
                tab4.setAnimation(outToLeftAnimation());
                tab2.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 5) {
                tab4.setAnimation(outToLeftAnimation());
                tab5.setAnimation(inFromRightAnimation());
            }
        }
        else if (currentTab == 5) {
            if (newTab == 1) {
                tab5.setAnimation(outToLeftAnimation());
                tab1.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 2) {
                tab5.setAnimation(outToLeftAnimation());
                tab2.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 4) {
                tab5.setAnimation(outToLeftAnimation());
                tab4.setAnimation(inFromRightAnimation());
            }
        }
        else if (currentTab == 3) {
            if (newTab == 1) {
                tab3.setAnimation(outToLeftAnimation());
                tab1.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 2) {
                tab3.setAnimation(outToLeftAnimation());
                tab2.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 4) {
                tab3.setAnimation(outToLeftAnimation());
                tab4.setAnimation(inFromRightAnimation());
            }
            else if (newTab == 5) {
                tab3.setAnimation(outToLeftAnimation());
                tab5.setAnimation(inFromRightAnimation());
            }
        }         
      SetCurrentTab(Integer.parseInt(tabId));
    }
private void SetCurrentTab(int tab) {
    this.currentTab = tab;
}

private int GetCurrentTab() {
    return this.currentTab;
}

最佳答案

如果您想避免过多的分配,您可以在 onCreate 中创建一次这些动画,然后稍后引用它们,而不是每次都创建一个新动画。

类似这样的事情:

private Animation mInFromRight;
private Animation mInFromLeft;

public Animation inFromRightAnimation() {
    return mInFromRight;
}

public Animation outToLeftAnimation() {
    return mInFromLeft;
}

@Override
protected void onCreate ( Bundle savedInstanceState ){
    super.onCreate(savedInstanceState);
    mInFromRight = new TranslateAnimation(
        Animation.RELATIVE_TO_PARENT, +1.0f,
        Animation.RELATIVE_TO_PARENT, 0.0f,
        Animation.RELATIVE_TO_PARENT, 0.0f,
        Animation.RELATIVE_TO_PARENT, 0.0f);
    mInFromRight.setDuration(500);

    mInFromLeft = new TranslateAnimation(
        Animation.RELATIVE_TO_PARENT, 0.0f,
        Animation.RELATIVE_TO_PARENT, -1.0f,
        Animation.RELATIVE_TO_PARENT, 0.0f,
        Animation.RELATIVE_TO_PARENT, 0.0f);
    mInFromLeft.setDuration(500);

    //...other oncreate code
}

除此之外,如果您在调用动画时仍然收到 GC,则这是您无法控制的。 Android 框架正在某个地方分配在动画过程中被销毁的对象。

GC 是正常的、必要的并且预计会发生,但您保持关注是件好事。大多数情况下,过多的 GC 是由于框架外部发生了一些愚蠢的事情,例如在循环中不必要地分配新对象。但框架也需要 GC,在本例中,这似乎就是正在发生的事情。

关于java - 动画导致垃圾收集器创建日志条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12008157/

相关文章:

java - 在 Java 的 JTextArea 中追加文本

android - Google Play - 通过 Alpha、Beta 和生产 channel 的审核流程

unity-game-engine - 使用 USS 样式在 Unity UI Toolkit 中循环过渡

JavaFX 切换带有幻灯片效果的场景

java - 如何在 Spring Boot 2.2.4 中将 @ConstructorBinding 和 @PropertySource 与 @ConfigurationProperties 一起使用?

java - 从 JPanel 获取 GridBagConstraints

java - 在华为 Android 7-10 上崩溃

android - 我可以将使用 android 支持的库与 Androidx 项目一起使用吗?

ios - -[AVMvidFrameDecoder advanceToFrame :] 'framebuffer num bytes' 中的 AVAnimator 断言失败

java - 通过 "new"创建一个 String 对象