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

什么时候叫他们?


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

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


你在你想要重绘的视图上使用invalidate(),它将使它的onDraw(Canvas c)被调用,requestLayout()将使整个布局渲染(测量阶段和定位阶段)再次运行。如果你在运行时改变子视图的大小,你应该使用它,但只有在特定的情况下,比如来自父视图的约束(我的意思是父视图的高度或宽度是WRAP_CONTENT,所以匹配测量子视图之前,他们可以再次包装他们)


为了更好地理解François BOURLIEUX和Dalvik提供的答案,我建议你看看Arpit Mathur的这张很棒的视图生命周期图:


无效()

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

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

请求布局()

如果视图的某些变化将影响大小,则应该调用requestLayout()。这将触发onMeasure和onLayout,不仅为这个视图,而且为父视图的所有方式。

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

invalidate();
requestLayout();

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

forceLayout ()

当父视图组上调用requestLayout()时,它不需要重新测量和重新布局它的子视图。但是,如果要在重测量和重新布局中包含子元素,那么可以在子元素上调用forceLayout()。forceLayout()只有在子节点上与直接父节点上的requestLayout()一起发生时才有效。单独调用forceLayout()将没有任何效果,因为它不会触发视图树上方的requestLayout()。

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

进一步的研究

创建视图类:添加属性和事件(有用的文档) 查看文档 查看源代码


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

正如你在forceLayout()的代码中看到的,它只是将视图标记为“需要重新布局”,但它既不计划也不触发该重新布局。重布局将不会发生,直到将来的某个时候,视图的父视图因为其他原因被布局。

在使用forceLayout()和requestLayout()时,还有一个更大的问题:

Let's say you've called forceLayout() on a view. Now when calling requestLayout() on a descendent of that view, Android will recursively call requestLayout() on that descendent's ancestors. The problem is that it will stop the recursion at the view on which you've called forceLayout(). So the requestLayout() call will never reach the view root and thus never schedule a layout pass. An entire subtree of the view hierarchy is waiting for a layout and calling requestLayout() on any view of that subtree will not cause a layout. Only calling requestLayout() on any view outside that subtree will break the spell.

我认为forceLayout()(以及它如何影响requestLayout()的实现是坏的,你不应该在你的代码中使用该函数。


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

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

requestLayout()——> onMeasure() and onLayout() and NOT Necessarily onDraw()

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

forceLayout()——> onMeasure()和onLayout()只是如果直接父调用requestLayout()。