[Android] setContentView 학습 노트

활동 시작

performLaunchActivity()

ActivityThread.performLaunchActivity() 메서드는 Android 시스템에서 활동을 시작하는 핵심 메서드입니다.

startActivity()활동을 시작하기 위해 메소드가 호출 되면 ActivityThread객체는 요청을 수신하고 performLaunchActivity() 메소드를 호출합니다.

performLaunchActivity() 메서드 내에서 ActivityRecord 对象시작할 활동을 나타내는 새 메서드가 먼저 생성됩니다.

다음으로 Activity 개체를 ActivityRecord 및 해당 속성 activity.attach() 과 연결하는 데 사용되는 메서드가 호출됩니다 .初始化

activity.attach() 메서드에서 PhoneWindow객체가 먼저 생성됩니다. PhoneWindow는 Activity와 관련된 창으로 창 관리 기능을 제공합니다.

mInstrumentation.callActivityOnCreate()그런 다음 활동의 수명 주기 콜백 메서드를 트리거하기 위해 메서드가 호출됩니다 onCreate().

mInstrumentation 활동 수명 주기 예약 및 이벤트 발송을 위한 도구 클래스입니다. onCreate(), onStart(), onResume() 등과 같은 다양한 수명 주기 콜백 메서드를 호출할 수 있습니다.

callActivityOnCreate() 메서드는 기본 스레드에서 활동의 onCreate() 메서드를 호출하여 일부 초기화 작업을 수행합니다.

onCreate() 레이아웃 설정, 전달된 데이터 가져오기 등과 같이 Activity가 생성될 때 필요한 초기화를 수행하는 데 사용되는 중요한 생명 주기 방법입니다.

폰윈도우

PhoneWindow 클래스는 주로 Android에서 디스플레이 인터페이스의 창 관리를 담당하며 다음과 같은 유형의 창을 생성합니다.

Activity:
활동을 시작하면 시스템에서 활동에 연결된 PhoneWindow 개체를 만듭니다. PhoneWindow 개체는 활동의 레이아웃 및 인터페이스 표시를 담당합니다.

Dialog(对话框):
Dialog 클래스는 대화 상자 형태로 표시되는 창으로 PhoneWindow에도 의존합니다. 대화를 만들 때 시스템은 대화의 레이아웃과 콘텐츠를 호스팅하기 위해 독립적인 PhoneWindow 개체를 만듭니다.

PopupWindow(弹出窗口):
PopupWindow는 다른 뷰 위에 떠 있는 창으로 PhoneWindow도 만들고 관리해야 합니다. PopupWindow 인스턴스를 생성하면 시스템에서 자동으로 PhoneWindow 객체를 생성합니다.

Toast(消息提示):
Toast 생성은 PhoneWindow에 직접 의존하지 않지만 Toast 메시지를 표시할 때 PhoneWindow를 통해 콘텐츠를 표시하기 위한 임시 창이 생성됩니다.

생성된 Activity가 Activity를 상속받을 때 setContentView를 호출

PhoneWindow.setContentView():
메서드는 Activity 에서 호출될 setContentView(layoutResID) 때 트리거됩니다 PhoneWindow 的 setContentView() . 주요 목적은 DecorView 콘텐츠 보기를 만들고 가져오는 것입니다.

installDecor():
installDecor() 메서드는 PhoneWindow의 전용 메서드로, DecorView 생성 및 획득을 담당합니다 mContentParent(内容视图的父容器).

generateDecor(-1):
installDecor() 메서드에서 generateDecor() 메서드를 호출하여 DecorView 객체를 생성하고 mDecor 멤버 변수에 저장합니다. 이 DecorView는 인터페이스 콘텐츠를 호스팅하는 PhoneWindow의 루트 보기입니다.

generateLayout(mDecor):
generateLayout() 메서드는 레이아웃을 생성하기 위한 보조 메서드 로 들어오는 DecorView를 통해 ViewGroup콘텐츠 뷰의 부모 컨테이너로 객체를 반환하고 mContentParent멤버 변수에 저장합니다.

mDecor.onResourcesLoaded(mLayoutInflater, layoutResource):
generateLayout() 메서드에서 onResourcesLoaded() mDecor 메서드를 호출하는데, 이는 리소스 로딩이 완료된 후 관련 작업을 처리하는 데 사용됩니다.

mLayoutInflater.inflate(layoutResID, mContentParent):
마지막으로 PhoneWindow에서 메서드를 호출하여 mLayoutInflater.inflate(layoutResID, mContentParent) 지정된 레이아웃 리소스(예: R.layout.activity_main)를 채우고 mContentParent인터페이스에서 레이아웃을 렌더링합니다.

여기에 이미지 설명 삽입

생성된 Activity가 AppCompatActivity를 상속받을 때 setContentView 호출

Activity 상속과 비교할 때 AppCompatActivity 상속 프로세스에는 호환성과 관련된 몇 가지 단계가 있습니다.

AppCompatDelegate.setContentView():
AppCompatActivity 에서 setContentView(layoutResID) 메서드를 호출할 때 트리거되는 메서드입니다 . 보장하는 역할을 합니다 .AppCompatDelegate setContentView() 正确的子布局(subDecor)被创建并设置为内容视图

ensureSubDecor():
ensureSubDecor() 메서드가 에 대해 호출됩니다 确保子布局 subDecor 被正确创建. createSubDecor()subDecor 개체를 생성하는 메서드를 호출합니다 .

createSubDecor():
createSubDecor() 메서드는 주로 创建 subDecor 对象인터페이스의 내용을 전달하는 역할을 합니다 根视图. ensureWindow()이 메서드에서는 연결된 항목이 PhoneWindow올바르게 생성되었는지 확인한 다음 를 mWindow.getDecorView()통해 PhoneWindow의 루트 보기를 가져오기 위해 호출됩니다 .

复制内容视图:
createSubDecor()이 메서드 에서 原始的内容视图(android.R.id.content)的子视图콘텐츠를 新的容器视图(R.id.action_bar_activity_content)하나로 복사하고 원본 콘텐츠 보기의 id 设置为 NO_ID는 입니다 新容器视图的 id 设置为 android.R.id.content.

设置 subDecor:
마지막으로 mWindow.setContentView(subDecor)subDecor를 PhoneWindow의 via 메서드로 설정합니다 内容视图.

布局创建与解析:
레이아웃을 생성하는 과정에서 LayoutInflater지정된 레이아웃 리소스가 구문 분석되고 反射创建해당 View 개체가 전달됩니다. 레이아웃 태그 이름에 패키지 이름이 포함되어 있으면 해당 항목이 reflection 을 통해 직접 생성되고 View 对象, 그렇지 않으면 onCreateView() 메서드를 통해 View 객체가 생성됩니다. 생성이 완료되면 서브뷰 생성 및 분석을 거쳐 최종적으로 전체 레이아웃의 뷰 구조를 얻게 된다.

여기에 이미지 설명 삽입

LayoutInflate 매개변수의 역할

LayoutInflater는 레이아웃 리소스 파일을 해당 뷰 개체로 변환하는 데 사용되는 Android의 클래스입니다. 주요 기능은 지정된 레이아웃 리소스 파일(XML 파일)에 따라 해당 뷰 계층을 생성하고 이를 View 개체로 인스턴스화하는 것입니다.

LayoutInflater를 사용하면 정적 XML 레이아웃 파일을 사용하지 않고도 코드에서 레이아웃을 동적으로 로드하고 생성할 수 있습니다. 이를 통해 런타임 시 필요에 따라 다양한 뷰를 동적으로 생성하고 해당 상위 컨테이너에 추가할 수 있습니다.

LayoutInflater의 여러 매개변수의 기능은 다음과 같습니다.

layoutResID:
로드해야 하는 레이아웃 리소스 파일의 ID입니다. 리소스 파일의 ID를 지정하면 LayoutInflater가 ID에 따라 해당 레이아웃 파일을 로드할 수 있습니다.

root:
레이아웃을 로드할 때 필요한 상위 컨테이너입니다. 레이아웃을 로드할 때 상위 컨테이너에 레이아웃을 추가해야 하는 경우 루트로 지정할 수 있습니다. 상위 컨테이너에 레이아웃을 추가할 필요가 없는 경우 루트를 null로 설정할 수 있습니다.

attachToRoot:
로드된 레이아웃 뷰를 루트 상위 컨테이너에 추가할지 여부를 나타내는 플래그입니다. true로 설정하면 로드된 레이아웃 뷰가 루트 상위 컨테이너에 직접 연결되고, false로 설정하면 로드된 레이아웃 뷰가 루트 상위 컨테이너에 추가되지 않고 반환만 됩니다.

// 方式一:将布局添加成功
View view = inflater.inflate(R.layout.inflate_layout, ll, true);
// 方式二:报错,一个View只能有一个父亲(The specified child already has a parent.)
View view = inflater.inflate(R.layout.inflate_layout, ll, true); // 已经addView
ll.addView(view);
// 方式三:布局成功,第三个参数为false
// 目的:想要 inflate_layout 的根节点的属性(宽高)有效,又不想让其处于某一个容器中
View view = inflater.inflate(R.layout.inflate_layout, ll, false);
ll.addView(view);
// 方式四:root = null,这个时候不管第三个参数是什么,显示效果一样
// inflate_layout 的根节点的属性(宽高)设置无效,只是包裹子View,
// 但是子View(Button)有效,因为Button是出于容器下的
View view = inflater.inflate(R.layout.inflate_layout, null, false);
ll.addView(view);
비고: 보기에 상위 컨테이너가 없습니다 =>>> 크기 매개변수 설정이 유효하지 않습니다.

requestWindowFeature()가 setContentView()보다 먼저 호출되어야 하는 이유

requestWindowFeature() 메서드는 실제로 PhoneWindow.requestFeature() 메서드를 호출합니다. mContentParentExplicitlySet 이 메소드는 이름이 지정된 변수가 인지 확인하고 있는 true경우 오류를 발생시킵니다.

PhoneWindow.setContentView() 메서드 호출 전에 requestWindowFeature()를 호출하는 목적은 레이아웃 콘텐츠를 설정하기 전에 창 기능이 요청되었는지 확인하는 것입니다. setContentView()이 이후에 requestWindowFeature()를 호출하면 먼저 호출되면 mContentParentExplicitlySet 变量会在 setContentView() 方法内部被设置为 true오류가 발생합니다 .

따라서 올바른 순서는 requestWindowFeature()를 호출하여 창 기능을 먼저 요청한 다음 setContentView()를 호출하여 레이아웃 콘텐츠를 설정하는 것입니다. 이것은 오류를 방지하고 필요한 창 기능을 올바르게 활성화합니다.

왜 이런 식으로 디자인 되었습니까?

Android의 창 레이아웃은 DecorView . DecorView는 제목 표시줄, 콘텐츠 영역 및 기타 장식 요소를 포함하여 활성 창의 모든 콘텐츠를 나타내는 루트 뷰입니다.

requestWindowFeature() 이 방법은 创建 DecorView 之前设置窗口的特征. 이렇게 하면 활성 창이 만들어질 때 특성 설정에 따라 창의 모양과 동작이 그려지는 방식이 결정됩니다.

setContentView() 메서드가 호출되면 DecorView가 생성되고 콘텐츠 영역이 추가됩니다. 이를 수행하기 전에 시스템은 DecorView를 그리는 방법을 결정하는 데 사용할 창 특성을 알아야 합니다. 그렇기 때문에 setContentView()를 호출하기 전에 requestWindowFeature()를 호출해야 합니다.

in 을 통해 requestWindowFeature() 中设置特征제목 표시줄, 진행률 표시줄 표시 여부 등 창의 모양과 기능을 제어할 수 있습니다. 이 설계 방식을 사용하면 활동 전에 레이아웃을 로드할 수 있습니다 对窗口进行必要的配置.

requestWindowFeature(Window.FEATURE_NO_TITLE); 설정이 잘못된 이유는 무엇입니까?

requestWindowFeature(Window.FEATURE_NO_TITLE) 설정이 작동하지 않는 이유는 활동이 AppCompatActivity활동에서 직접 상속되는 것이 아니라 에서 상속되기 때문입니다. AppCompatActivity에서 제목 표시줄의 처리는 기존 활동의 처리와 다릅니다.

AppCompatActivity에서 supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 제목 표시줄을 숨기도록 요청하는 메서드를 사용해야 합니다. 이는 AppCompatActivity가 다양한 버전의 Android에서 제목 표시줄이 일관되게 숨겨지도록 하는 호환성 기능을 지원하기 때문입니다.

supportRequestWindowFeature() 메서드는 창 기능을 설정하는 AppCompatActivity의 메서드입니다. supportRequestWindowFeature(Window.FEATURE_NO_TITLE)를 호출하여 활동에서 제목 표시줄을 숨기도록 요청할 수 있습니다.

따라서 액티비티가 에서 상속되고 AppCompatActivity제목 표시줄을 숨기려면 supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 대신 메서드를 사용해야 합니다 requestWindowFeature(Window.FEATURE_NO_TITLE). 전자는 제목 표시줄 숨기기가 올바르게 처리되도록 합니다.

Supongo que te gusta

Origin blog.csdn.net/qq_43358469/article/details/131889088
Recomendado
Clasificación