【问题标题】:How to reduce requestLayout() lag in animations?如何减少动画中的 requestLayout() 滞后?
【发布时间】:2019-03-11 07:30:30
【问题描述】:

我正在尝试为TextView 的宽度设置动画,在我的 Redmi Note 4 上它运行良好。然而,在速度稍慢的手机(1.2 GHz 四核)上进行测试时,动画的延迟非常糟糕。

经过一些入门调试,原来是调用requestLayout()是罪魁祸首,它丢了很多帧,经过进一步检查,原来是onMeasure()这是重绘时调用的第一个方法 , 被称为很多只有 1 TextView 被动画。父层次结构的其余部分很可能将其称为“冒泡”到根。

在我的情况下,这绝对不是 bueno。我正在尝试为宽度和高度设置动画。我使用ValueAnimator 并在onAnimationUpdate() 内部调用requestLayout,我尝试仅在其中一个内部调用requestLayout(),但它几乎没有任何影响。

final ViewGroup.LayoutParams layoutParams = container.getLayoutParams();

ValueAnimator anim = ValueAnimator.ofInt(this.width, ((int) (this.screenWidth / 1.5)));
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        layoutParams.width = (int) (Integer) valueAnimator.getAnimatedValue();
    }
});
anim.setDuration(duration);
anim.start();

anim = ValueAnimator.ofInt(this.height, this.screenHeight / 2);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        layoutParams.height = (int) (Integer) valueAnimator.getAnimatedValue();
        container.requestLayout();
    }
});
anim.setDuration(duration);
anim.start();

我尝试制作自定义 StaticLayout 以利用这种方法的一些效率和性能优化,但它也没有帮助。毕竟 View 类本身就是反复调用 onMeasure() 的东西,那么我该如何防止这种情况,只更新我愿意调整大小的 TextView 呢?当然invalidate() 不会起作用,因为它会错过调整大小的工作。

【问题讨论】:

    标签: android performance android-layout optimization drawing


    【解决方案1】:

    我认为这取决于设备的图形渲染能力。 所以你得到了设备的差异。 如果有掉帧,你不应该对此感到惊讶。

    一个原因可能是: - 您正在从某个宽度动画到 screenWidth/1.5,我认为这非常大。

    假设你的动画是从 48 到 480

    初始值:48

    最终值:480

    持续时间:200 毫秒

    这意味着 (480-48) = 432 步/在 200 毫秒内重新绘制 然后,大约每毫秒绘制 2 次。

    因此,您为 1 次绘图提供的时间不到一毫秒。 理想情况下,如果时间绘制时间超过 16 毫秒,那么就会出现丢帧。 在您的情况下,由于 requestLayout 调用,您正在尝试过多的重新绘制。

    绘制 432 帧的理想条件如下:

    1 frame -> 20 ms (some extra time given) 432 frames -> 8640 ms

    尽量减少对 requestLayout 的调用次数,以防止onMeasure() 调用。

    【讨论】:

    • 我尝试在动画中跳过奇数/偶数迭代,但这导致动画非常卡顿。
    【解决方案2】:

    经过一番挖掘,我发现在ConstraintLayout 上使用beginDelayedTransition()ConstraintSet 证明比手动动画更高效、更流畅。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-22
      • 2015-04-13
      • 2013-10-27
      • 1970-01-01
      相关资源
      最近更新 更多