215

我对类的角色和forceLayout()方法有点困惑。requestLayout()invalidate()View

什么时候叫他们?

4

6 回答 6

398

为了更好地理解François BOURLIEUXDalvik提供的答案,我建议你看看Arpit Mathur的这个很棒的视图生命周期图: 在此处输入图像描述

于 2014-09-15T10:44:20.597 回答
153

invalidate()

invalidate()当您想要安排重绘视图时,调用完成。它将导致onDraw最终被调用(很快,但不是立即)。自定义视图何时调用它的一个示例是文本或背景颜色属性发生更改时。

视图将被重绘,但大小不会改变。

requestLayout()

如果您的视图发生了会影响大小的更改,那么您应该调用requestLayout(). 这不仅会触发此视图onMeasure,还会触发onLayout父视图。

调用requestLayout()保证会导致onDraw(与接受答案中的图表所暗示的相反),因此它通常与invalidate().

invalidate();
requestLayout();

这方面的一个示例是自定义标签的文本属性发生更改。标签会改变大小,因此需要重新测量和重新绘制。

forceLayout()

requestLayout()父视图组上有一个调用时,不需要重新测量和重新布局其子视图。但是,如果孩子应包括在重新测量和重新布局中,那么您可以拜访forceLayout()孩子。仅当它与直接父forceLayout()级的 a 一起出现时才适用于子级。requestLayout()单独调用forceLayout()不会有任何效果,因为它不会触发requestLayout()视图树。

阅读此问答以获得更详细的描述forceLayout()

进一步研究

于 2017-02-24T04:19:16.830 回答
30

在这里你可以找到一些回应:http: //developer.android.com/guide/topics/ui/how-android-draws.html

对我来说,调用invalidate()只刷新视图,调用requestLayout()刷新视图并计算屏幕上视图的大小。

于 2012-12-13T10:51:18.677 回答
5

invalidate()--->onDraw()从 UI 线程

postInvalidate()--->onDraw()从后台线程

requestLayout()--->onMeasure()并且onLayout()AND不一定 onDraw()

  • 重要提示:调用此方法不会影响被调用类的子类。

forceLayout()--->onMeasure()并且onLayout() 只要直接父级调用requestLayout().

于 2020-06-13T09:45:49.633 回答
3

您在要重绘的视图上使用 invalidate() ,它将使其 onDraw(Canvas c) 被调用,并且 requestLayout() 将使整个布局渲染(测量阶段和定位阶段)再次运行。如果您在运行时更改子视图的大小,则应该使用它,但仅在特定情况下,例如来自父视图的约束(我的意思是父视图的高度或宽度是 WRAP_CONTENT ,因此匹配测量子视图,然后才能再次包装它们)

于 2014-07-19T00:14:59.127 回答
3

这个答案是不正确的forceLayout()

正如您在代码中forceLayout()看到的那样,它只是将视图标记为“需要重新布局”,但它既不安排也不触发重新布局。直到将来某个时候,视图的父级由于其他原因被布局,才会发生重新布局。

forceLayout()使用and时还有一个更大的问题requestLayout()

假设您调用forceLayout()了视图。现在,当调用requestLayout()该视图的后代时,Android 将递归调用requestLayout()该后代的祖先。问题是它会在您调用的视图上停止递归forceLayout()所以requestLayout()调用永远不会到达视图根,因此永远不会安排布局传递。视图层次结构的整个子树正在等待布局,调用requestLayout()该子树的任何视图都不会导致布局。只有调用requestLayout()该子树之外的任何视图才能打破咒语。

我会考虑forceLayout()(以及它如何影响requestLayout()被破坏,你不应该在你的代码中使用该函数。

于 2017-06-27T13:25:44.070 回答