Usage of forceLayout(), requestLayout() and invalidate()
I'm a bit confused about the roles of forceLayout()
, requestLayout()
and invalidate()
methods of the View
class.
When shall they be called?
To better understand answers provided by François BOURLIEUX and Dalvik I suggest you take a look at this awesome view lifecycle diagram by Arpit Mathur:
invalidate()
Calling invalidate()
is done when you want to schedule a redraw of the view. It will result in onDraw
being called eventually (soon, but not immediately). An example of when a custom view would call it is when a text or background color property has changed.
The view will be redrawn but the size will not change.
requestLayout()
If something about your view changes that will affect the size, then you should call requestLayout()
. This will trigger onMeasure
and onLayout
not only for this view but all the way up the line for the parent views.
Calling requestLayout()
is not guaranteed to result in an onDraw
(contrary to what the diagram in the accepted answer implies), so it is usually combined with invalidate()
.
invalidate();
requestLayout();
An example of this is when a custom label has its text property changed. The label would change size and thus need to be remeasured and redrawn.
forceLayout()
When there is a requestLayout()
that is called on a parent view group, it does not necessary need to remeasure and relayout its child views. However, if a child should be included in the remeasure and relayout, then you can call forceLayout()
on the child. forceLayout()
only works on a child if it occurs in conjunction with a requestLayout()
on its direct parent. Calling forceLayout()
by itself will have no effect since it does not trigger a requestLayout()
up the view tree.
Read this Q&A for a more detailed description of forceLayout()
.
Further study
- Creating a View Class: Add Properties and Events (helpful docs)
- View documentation
View
source code
Here you can find some response: http://developer.android.com/guide/topics/ui/how-android-draws.html
For me a call to invalidate()
only refreshes the view and a call to requestLayout()
refreshes the view and compute the size of the view on the screen.
invalidate()
---> onDraw()
from UI thread
postInvalidate()
---> onDraw()
from background thread
requestLayout()
---> onMeasure()
and onLayout()
AND NOT Necessarily onDraw()
- IMPORTANT: Calling this method does not affect the called class's child.
forceLayout()
---> onMeasure()
and onLayout()
JUST IF the direct parent called requestLayout()
.
you use invalidate() on a view that you want to redraw, it'll make its onDraw(Canvas c) to invoked, and requestLayout() will make the whole layout rendering ( measurement phase and positioning phase) run again. You should use it if you are changing child view's size on runtime but only in particular cases like constraints from the parent view(by that I mean that the parent height or width are WRAP_CONTENT and so match measure the children before they can wrap them again)