forceLayout (), requestLayout () 및 invalidate () 사용


185

나는의 역할에 대한 혼란 조금 해요 forceLayout(), requestLayout()그리고 invalidate()의 방법 View클래스입니다.

그들은 언제 부를 것인가?

답변:


357

François BOURLIEUXDalvik의 답변을 더 잘 이해하려면 Arpit Mathur 의이 멋진 뷰 수명주기 다이어그램을 살펴 보는 것이 좋습니다 . 여기에 이미지 설명을 입력하십시오


28
무효화가 호출 된 후 requestLayout이 직접 호출되는 경우가 종종 있습니다 .Android 소스 코드에서 TextView와 같은 일이 발생하는 것을 볼 수도 있지만이 다이어그램에 따르면 중복됩니다. 그렇게 할 목적이 있습니까?
tcox

5
글쎄, 그것은 흥미로운 질문이며, 솔직히 말해서 왜 그들이 두 가지 방법을 모두 호출하는지 모르겠습니다 TextView. 나는 그들이을 그리려는 어쩌면 그 생각 View들이 레이아웃 관련 매개 변수를 변경하기 전에 마지막으로,하지만 우리는 다른 순서로 호출되는 이러한 호출 생각해 보면 정말 이해가되지 않습니다 (그들은 호출 invalidate()직후 requestLayout()TextView게다가). 어쩌면 StackOverflow :)에 대한 또 다른 질문이 필요합니까?
Bartek Lipinski

14
(1/2) : 나는 당신이 그 두 가지 방법 ( invalidate()requestLayout())을 올바르게 이해하지 못한다고 생각합니다 . 이러한 방법의 목적은 View어떤 종류의 무효화 가 발생 했는지 알려주는 것 입니다. View이러한 메소드 중 하나를 호출 한 후 따라야 할 경로를 결정하는 것은 아닙니다 . View-lifecycle-path 선택의 논리 는 자신을 호출 할 적절한 방법을 선택하는 것입니다. 크기 변경과 관련 requestLayout()이있는 경우 (호출해야 함) 크기를 변경하지 않은 상태에서 시각적 변경 만있는 경우을 호출해야합니다 invalidate().
Bartek Lipinski

11
(2/2) : 당신이 당신의 크기를 변경하는 경우 View어떤 방법으로, 예를 들어, 당신은 현재의 수LayoutParams (A)의 View당신은 그들을 수정할 수 있지만 NOT 중 전화 requestLayout또는 setLayoutParams(호출하는 requestLayout다음 호출 할 수 있습니다, 내부적으로) invalidate()당신이 원하는만큼, 그리고 이 View때문에 크기를 변경하지 않습니다, 측정 레이아웃 과정을 거쳐야하지 않습니다. 당신이 말하지 않으면 View그 크기가 (A로 변경하는 requestLayout메소드 호출), 다음은 View그것을하지 않았다 가정 것이고, onMeasureonLayout호출되지 않습니다.
Bartek Lipinski


125

invalidate()

invalidate()뷰 다시 그리기를 예약하려는 경우 호출 이 수행됩니다. 그것은 발생합니다 onDraw(그러나 즉시, 곧) 결국 호출되는. 사용자 정의보기에서 호출하는 예는 텍스트 또는 배경색 속성이 변경된 경우입니다.

뷰가 다시 그려 지지만 크기는 변경되지 않습니다.

requestLayout()

보기에 대한 내용이 변경되어 크기에 영향을 줄 경우을 호출해야합니다 requestLayout(). 이 트리거 onMeasureonLayout부모 뷰 라인 업 방식이 뷰를 제외한 모든 아닙니다.

호출 requestLayout()은 (허용 된 답변의 다이어그램이 의미하는 것과는 달리) 결과를 보장하지 않으므로onDraw 일반적으로와 결합됩니다 invalidate().

invalidate();
requestLayout();

예를 들어 맞춤 라벨의 텍스트 속성이 변경된 경우입니다. 라벨 크기가 변경되므로 다시 측정하고 다시 그려야합니다.

forceLayout()

있을 때 requestLayout()부모 뷰 그룹에서 호출되는, 그렇지 재 측정을하고 아이 뷰 레이아웃 작업에 필요한 필요하지 않습니다. 그러나 재 측정 및 중계에 아동을 포함시켜야하는 경우 아동에게 전화를 걸 수 있습니다 forceLayout(). 직계 부모 forceLayout()와 함께 발생하는 경우에만 아동에게 적용됩니다 requestLayout(). 뷰 트리를 forceLayout()트리거하지 않기 때문에 자체 호출 은 효과가 없습니다 requestLayout().

에 대한 자세한 설명은 이 Q & A 를 읽으십시오 forceLayout().

추가 연구


1
그러나 먼저 requestLayout ()을 호출 한 다음 invalidate ()을 호출하는 것이 더 합리적이지 않습니까?
scholt

2
@ scholt, 내가 아는 한 순서는 중요하지 않으므로 원하는 경우 전화 requestLayout()를 걸 수 있습니다 invalidate(). 어느 쪽도 레이아웃을 만들거나 즉시 그릴 수 없습니다. 오히려 그들은 결국 릴레이 아웃 및 다시 그리기 결과 플래그를 설정합니다.
Suragch

27

여기에 몇 가지 응답이 있습니다. http://developer.android.com/guide/topics/ui/how-android-draws.html

나에게 전화를 걸면 invalidate()뷰가 requestLayout()새로 고쳐지고 전화를 걸면 뷰 가 새로 고쳐지고 화면 크기가 계산됩니다.


3
forceLayout ()은 어떻습니까?
sdabet

@fiddler,이 메소드는 PFLAG_FORCE_LAYOUT 및 PFLAG_INVALIDATED의 두 플래그를 설정합니다.
suitianshi

7
@suitianshi 플래그를 설정하면 어떤 결과가 발생합니까?
Sergey

1
@Sergey 결과적으로이 플래그는 측정 캐시를 재정의합니다 (뷰는 캐시를 사용하여 동일한 MeasureSpec에 대해 향후 더 빨리 측정합니다). 여기 View.java 라인 18783를 참조하십시오 github.com/android/platform_frameworks_base/blob/master/core/...
RhetoricalRuvim에게

3

다시 그리려는 뷰에서 invalidate ()를 사용하면 onDraw (Canvas c)가 호출되고 requestLayout ()은 전체 레이아웃 렌더링 (측정 단계 및 위치 지정 단계)을 다시 실행합니다. 런타임에 자식보기의 크기를 변경하고 부모보기의 제약 조건과 같은 경우에만 사용해야합니다 (부모 높이 또는 너비가 WRAP_CONTENT이므로 자식을 다시 래핑하기 전에 측정하여 일치시킵니다)


3

이 답변 은에 대해 정확하지 않습니다 forceLayout().

코드forceLayout() 에서 볼 수 있듯이 뷰는 "중계가 필요"로 표시되지만 해당 중계를 예약하거나 트리거하지는 않습니다. 향후 어느 시점에서보기의 부모가 다른 이유로 배치 될 때까지 릴레이 아웃이 발생하지 않습니다.

forceLayout()and를 사용할 때 훨씬 더 큰 문제가 있습니다 requestLayout().

당신이 forceLayout()보기에 전화했다고 가정 해 봅시다 . 이제 requestLayout()해당 뷰의 자손을 호출 할 때 Android는 requestLayout()해당 자손의 조상을 재귀 적으로 호출 합니다. 문제는 호출 한보 기에서 재귀를 중지한다는 것입니다 forceLayout(). 따라서 requestLayout()호출은 뷰 루트에 도달하지 않으므로 레이아웃 패스를 예약하지 않습니다. 뷰 계층 구조의 전체 하위 트리가 레이아웃을 기다리고 requestLayout()있으며 해당 하위 트리의 뷰를 호출 해도 레이아웃이 발생하지 않습니다. 해당 requestLayout()서브 트리 외부의 뷰만 호출 하면 철자가 깨집니다.

나는 구현을 고려할 것이다 forceLayout()(그리고 그것이 어떻게 영향 requestLayout()을 미치는지 깨달았 으므로 코드에서 그 기능을 사용해서는 안된다.


1
안녕하세요! 그 주문을 어떻게 생각해 습니까? 어딘가에 기록되어 있습니까?
azizbekian 2016 년

1
불행히도 문서화되지 않았으며 의도조차도 없습니다. 나는 코드를 조사 View하고 문제를 직접 실행하고 디버깅하여 알아 냈습니다 .
fluidsonic

그런 다음 forceLayout()API 의 목적이 궁금 합니다. 실제로 레이아웃 패스를 강제하지는 않지만 에서 관찰되는onMeasure() 플래그 변경 하지만 명시 적 또는 명시 적 onMeasure()호출이 없으면 호출되지 않습니다 . 즉, 와 쌍을 이루어야합니다 . 반면에 여전히 수행해야하는 경우 수행해야하는 이유는 무엇입니까? requestLayout()View#measure()forceLayout()requestLayout()forceLayout()requestLayout()
azizbekian 2016 년

@azizbekian 아니오, 당신은 필요하지 않습니다. 또한 requestLayout()모든 일을 forceLayout()합니다.
fluidsonic

1
@Suragch는 그 중 하나를 놓쳤습니다. 감사합니다! 매우 흥미로운 분석. 의도 된 사용 forceLayout이 의미가 있습니다. 결국에는 이름이 매우 잘못 지정되고 문서화되었습니다.
fluidsonic

0

invalidate()onDraw()UI 스레드에서 --->

postInvalidate()onDraw()배경 스레드에서 --->

requestLayout()---> onMeasure()onLayout()AND 반드시 onDraw()

  • 중요 :이 메서드를 호출해도 호출 된 클래스의 자식에는 영향을 미치지 않습니다.

forceLayout()---> onMeasure()그리고 onLayout() 그냥 직계 부모가 전화 했다면requestLayout() .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.