안드로이드 findViewById 동작 원리 파헤치기
https://velog.io/@ows3090/Android-findViewById-원리
[Android] findViewById 원리
findViewById란? 안드로이드 개발에서 findViewById 메소드는 레이아웃에 있는 뷰를 리소스 id를 통해서 원하는 뷰 객체를 가져올 수 있는 메소드입니다. 그 전에 setContentView와 같은 메소드로 xml에 있는
velog.io
이 글은 findViewById의 내부 동작 원리를 파악하기 위해 작성된 것이다. 위의 링크를 참고하여 직접 코드를 살펴보며 확인하고자 한다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(**findViewById(R.id.main)**) { v: View, insets: WindowInsetsCompat ->
// ...
}
// ...
}
findViewById 파고들어 가 보기
findViewById는 Activity에서 호출 시 Window의 findViewById를 호출하게 되고, Window에서는 View의 findViewById를 호출한다.

[Activity.java] findViewById
//Activity.java
@Nullable
public <T extends View> T findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
public Window getWindow() {
return mWindow;
}
@UnsupportedAppUsage
private Window mWindow;
▼ 파고들기
[Window.java] findViewById
// Window.java
@Nullable
public <T extends View> T findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
public abstract @NonNull View getDecorView();
▼ 파고들기
[View.java] findViewById ⇒ findViewTraversal
// View.java
@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
if (id == NO_ID) {
return null;
}
return findViewTraversal(id);
}
protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
return (T) this;
}
return null;
}
- Activity의 findViewById는 Window에 있는 것을 호출하고, Window의 findViewById는 View에 있는 것을 호출하여 최종적으로 findViewTraversal 메서드까지 호출하게 된다.
- findViewTraversal은 호출된 View의 ID와 매개변수의 ID를 비교하여 동일할 때 View 자체를 리턴하는 구조다.
[ViewGroup.java] ViewGroup의 findViewTraversal
// ViewGroup.java
@Override
protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
return (T) this;
}
final View[] where = mChildren;
final int len = mChildrenCount;
for (int i = 0; i < len; i++) {
View v = where[i];
if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
return (T) v;
}
}
}
return null;
}
- ViewGroup의 findViewTraversal은 자식 뷰 배열인 mChildren을 순회하며 매칭되는 ID를 찾는다. 일치하는 뷰가 발견되면 반환하고 탐색을 종료한다.
- 만약 자식 뷰 중에 또 다른 ViewGroup이 존재한다면, 해당 ViewGroup의 findViewById와 findViewTraversal이 재귀적으로 호출된다. 결과적으로 트리 구조에서 깊이 우선 탐색(DFS) 방식으로 각 뷰의 ID가 동일한지 하나씩 확인하면서 찾는 방식으로 동작한다.
- 결과적으로, findViewById는 여러 ViewGroup을 순회하며 필요한 View를 찾는 방식으로 동작한다. 이러한 구조 때문에 findViewById를 여러 번 호출하면 시간 복잡도가 증가하는 이유도 여기에 있다. 또한 특히, 순회 중에 null이 반환되면 런타임 오류가 발생할 위험이 있다.
이러한 구조를 이해함으로써 컴파일 타임에 바인딩을 지원하는 ViewBinding이 왜 필요한지 그 이유를 알게 되었다.
다음으로 읽으면 좋은 글 추천
https://yujinius45.tistory.com/124
[Android] 안드로이드에서 findViewById 완벽 가이드: 사용법, 동적 뷰 조작, 문제점과 해결 방법
안드로이드에서 findViewById 완벽 가이드: 사용법, 동적 뷰 조작, 문제점과 해결 방법목차findViewById 개요findViewById 기본 사용법: MainActivity에서 뷰에 접근하기동적 뷰 삽입 및 삭제 실습Layout Inspector
yujinius45.tistory.com
'Android' 카테고리의 다른 글
| [Android] Unresolved reference: BR.isTextLongEnough 에러 해결 (1) | 2024.11.16 |
|---|---|
| [Android] DataBinding 동작 원리 파헤치기 (0) | 2024.11.10 |
| [Android] 안드로이드 ViewBinding 완벽 가이드: 개념, 도입 배경, 사용법, 동작 방식 및 컴파일 위치 (9) | 2024.11.09 |
| [Android] ViewBinding 동작 원리 파헤치기 (4) | 2024.11.09 |
| [Android] 안드로이드에서 findViewById 완벽 가이드: 사용법, 동적 뷰 조작, 문제점과 해결 방법 (0) | 2024.11.09 |