我最近注意到我的应用存在严重的性能问题。我基本上有以下布局......
描述
简而言之,有一个ViewPager
,它持有3个RelativeLayout
作为页面。在每个页面中都有许多 TextView
。我最近注意到当我输入 EditText
时有很多滞后,它上面有一个 TextWatcher
来执行快速 SQL 查询以自动完成。我的 HTC One M8 在我输入文本时卡顿和滞后,但我知道这不是查询速度慢,因为我测量查询只用了大约 7 毫秒。
我使用了方法分析、Systrace 和普通的老式 Log
调试并得出结论,每次我在 EditText
中键入一个字符时大约 1,700对 onMeasure
的调用是在 RelativeLayout
A、B 和 C 中的 TextView
上进行的。总共只有大约 15 个独立的 TextView
跨页面。我注意到 每个 onMeasure
都被调用了数百次,而不是像通常那样只调用一两次。
问题
我不知道为什么在页面 B 中输入 EditText
会导致页面 A 和 C 中的其他 TextView
也“重新测量”。更重要的是,是否有人了解为什么如此频繁地调用 onMeasure
?而且,有谁知道可以显着减少对 onMeasure
的调用次数的解决方案吗?
详情
这可能会有所帮助:我实际上能够通过删除 RelativeLayout
2 将 onMeasure
调用的次数减少到大约 900,这可能建议传播 onMeasure
调用在 ViewPager
之外开始。
最佳答案
虽然我没有足够的信息来确定具体问题,但我可以大致告诉您发生了什么:
对 Root View 的 measure
的调用会导致对每个 subview 的 measure
的调用,依此类推,沿着树向下。
假设称为“当前 View ”的 View 在要求其每个 subview 进行 self 测量后决定没有足够的空间容纳所有 subview 。它会要求他们每个人再次测量自己,建议最大尺寸。那么,假设名为“Relative Layout B”的 View 根据指定的最大值从根本上改变了它的大小。因为变化太大,“现在的看法”必须每个 child 多问一遍。这个循环很容易需要更多的迭代来解决。
当“当前 View ”决定其大小时,它会向“View Pager”报告。假设“View Pager”没有足够的空间容纳它的三个 View ,不得不要求它们重新测量,最大。我们现在至少调用了 20 次 TextView 的 onMeasure
。如果 ViewPager 上方的每个其他 View 都迭代几次,很快您就会开始看到很大的数字。
正如您已经指出的那样,最好的解决方案是减少该树的深度。或者,您可以使用具有更简单测量算法的布局管理器(FrameLayout、LinearLayout)
1500 已经很多了。其中一种观点是做一些奇怪的事情。您应该能够非常简单地识别它,使用 DDMS 套件中的 TreeView 工具。在 eclipse 中它被称为“TreeView”。在 Studio 中,单击 Android 图标并切换到 Hierarchy View 透视图。您也可以从 SDK 工具目录中的命令行运行它。
添加: 如果您在运行时将 Hierarchy Viewer 连接到您的应用程序,您将在其中一个 Pane 中看到整个 View 树。树中的每个节点底部都有三个彩色橡皮糖。第一个橡皮糖代表测量阶段。如果橡皮糖是绿色的,则该 View 的测量阶段很快。如果它是黄色的,则该节点位于布局中节点的前 50 个百分位。如果它是红色的,它是布局中最慢的。
您应该能够沿着一条黄色的轨迹一直走到有问题的 View 。
关于android - onMeasure 被调用 1,500 多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25331004/