Android:如何避免多次衡量调用

时间:2015-10-08 06:53:06

标签: android performance layout

我有一个DialogFragment具有中等复杂度的布局(大约50个视图,请参阅下面的结构)。

在某些计算之后,我必须在同一方法中更新多达10个字段。 问题是更新会导致有形的UI延迟(在我的测试手机上大约0.5秒)。

我已经描述了我的对话:
1)我的计算和我的更新代码需要<5ms才能运行
2)大约95%的CPU时间采用与度量相关的方法(如onMeasure()measureHierarchy()measureChildWithMargins()等) 我以前从未遇到过这种行为。

问题
1) Android会在每次更新后重新测量所有布局(即使它们是一个接一个地完成)吗? 2)有没有办法强制仅测量后全部值更新(比如在设置值之前停止测量并在之后恢复)?
3)我还应该在哪里寻找问题?

非常感谢!

布局结构:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" >
    <ScrollView>
        <RelativeLayout>
            <CheckBox />
            <TextView />
            <TextView />
            <TextView />
            <CheckBox />
            <RelativeLayout>
                <RadioButton />
                <Spinner />
                <TextView />
                <RadioButton />
                <TextView />
                <TextView />
                <TextView />
            </RelativeLayout>
            <RelativeLayout>
                <RadioButton />
                <Spinner />
                <RadioButton />
                <TextView />
                <TextView />
                <TextView />
                <RadioButton />
                <TextView />
                <TextView />
                <TextView />
                <RadioButton />
                <Spinner />
                <TextView />
                <TextView />
                <RadioButton />
                <TextView />
                <TextView />
                <LinearLayout>
                    <TextView />
                    <TextView />
                    <TextView />
                    <TextView />
                    <TextView />
                    <TextView />
                    <TextView />
                </LinearLayout>
            </RelativeLayout>
            <View />
        </RelativeLayout>
    </ScrollView>
    <include />
</RelativeLayout>

1 个答案:

答案 0 :(得分:1)

Android OS正在关注UI刷新。因此,一旦您通过.set设置了某些内容,UI就会更新。可能会有一些优化,但我不知道它们。

有一些选项可以节省CPU时间。

  1. 您可以在后台线程上构建视图,然后只执行root_view.addView(child_view),其中root_view是在主线程上生成的一些空视图,而子视图包含整个视图层次结构。如果使用此方法测量,则每次调用.set时都不会执行布局和其他慢速方法。在大多数情况下,这种方法运作良好。

  2. 如果您无法在后台线程上创建视图,则可以尝试覆盖这些视图的measure(),layout(),draw()方法。应该有一些布尔标志,它将指示您是否要对UI进行更多更新,或者这将是最后一个。因此,如果该标志表明会有更多更新,您可以&#34;返回&#34;从以上三个函数中完全没有计算任何东西,否则只需调用super.measure(),super.draw(),super.layout()。

    protected void measure(...) {
        if (flag)
            return;
        super.measure();
    }
    
  3. 在我的项目中,我使用第一种方法。第二个是....如果没有别的你可以做,我绝对不推荐它。

    希望这会对你有所帮助:)。