【Android】setContentView的学习笔记

news2024/11/25 4:21:41

启动一个Activity

performLaunchActivity()

ActivityThread.performLaunchActivity() 方法是 Android 系统中负责启动一个 Activity 的关键方法。

当调用startActivity()方法启动一个 Activity 时,ActivityThread 对象会接收到该请求,并调用 performLaunchActivity() 方法。

在 performLaunchActivity() 方法内部,首先会创建一个新的 ActivityRecord 对象,用于表示将要启动的 Activity。

接下来,会调用 activity.attach() 方法,该方法用于将 Activity 对象与 ActivityRecord 关联起来,并初始化相应的属性。

在 activity.attach() 方法中,首先会创建一个PhoneWindow对象。PhoneWindow 是与 Activity 关联的窗口,提供了窗口管理的功能。

然后,会调用mInstrumentation.callActivityOnCreate()方法来触发 Activity 的生命周期回调方法 onCreate()

mInstrumentation 是用于进行 Activity 生命周期调度和事件派发的工具类。它可以调用各种生命周期回调方法,如 onCreate()、onStart()、onResume() 等。

callActivityOnCreate() 方法会在主线程中调用 Activity 的 onCreate() 方法,以便执行一些初始化操作。

onCreate() 是一个重要的生命周期方法,用于在 Activity 创建时进行必要的初始化,如设置布局、获取传递的数据等。

PhoneWindow

PhoneWindow 类在 Android 中主要负责显示界面的窗口管理,它会创建以下几种类型的窗口

Activity:
当你启动一个 Activity 时,系统会为该 Activity 创建一个关联的 PhoneWindow 对象。这个 PhoneWindow 对象负责承载 Activity 的布局和界面显示。

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() 方法中,会调用 mDecor 的 onResourcesLoaded() 方法,该方法用于处理资源加载完成后的相关操作。

mLayoutInflater.inflate(layoutResID, mContentParent):
最后,在 PhoneWindow 中调用 mLayoutInflater.inflate(layoutResID, mContentParent) 方法,将指定的布局资源(例如 R.layout.activity_main)填充到 mContentParent 中,从而将布局渲染到界面上。

在这里插入图片描述

当创建的Activity继承AppCompatActivity时,调用setContentView

继承 AppCompatActivity 的流程相比于继承 Activity 会多出一些处理与兼容性相关的步骤。

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 的内容视图

布局创建与解析:
在创建布局的过程中,会使用LayoutInflater解析指定的布局资源,并通过反射创建相应的 View 对象。如果布局标签名包含了包名,则直接通过反射创建对应的 View 对象;否则,会通过 onCreateView() 方法来创建 View 对象。在创建完毕后,将会进行子视图的创建解析,最终得到整个布局的视图结构。

在这里插入图片描述

LayoutInflate参数的作用

LayoutInflater 是 Android 中的一个类,用于将布局资源文件转换为对应的视图对象。它的主要作用是根据指定的布局资源文件(XML 文件)创建对应的视图层次结构,并将其实例化为 View 对象。

通过 LayoutInflater,可以在代码中动态地加载和创建布局,而不需要使用静态的 XML 布局文件。这样可以在运行时根据需要动态地创建不同的视图,并将其添加到相应的父容器中。

LayoutInflater 的几个参数的作用如下:

layoutResID:
这是需要加载的布局资源文件的 ID。通过指定资源文件的 ID,LayoutInflater 可以根据该 ID 加载对应的布局文件。

root:
这是加载布局时所需的父容器(parent)。在加载布局时,如果需要将布局添加到一个父容器中,可以将其指定为 root。如果不需要将布局添加到父容器中,可以将 root 设置为 null。

attachToRoot:
这是一个标志位,用于指示是否将加载后的布局视图添加到 root 父容器中。如果设置为 true,则会将加载后的布局视图直接附加到 root 父容器中;如果设置为 false,则只会返回加载后的布局视图,而不会将其添加到 root 父容器中。

举例
// 方式一:将布局添加成功
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);
备注:View 没有父容器 =>>> 尺寸大小 参数的设置无效

为什么requestWindowFeature()要在setContentView()之前调用

requestWindowFeature() 方法实际上是调用了 PhoneWindow.requestFeature() 方法。这个方法会检查一个名为 mContentParentExplicitlySet 的变量是否为 true,如果是则会报错。

在 PhoneWindow.setContentView() 方法调用之前调用 requestWindowFeature() 的目的是确保在设置布局内容之前先请求窗口功能。如果先调用 setContentView(),那么 mContentParentExplicitlySet 变量会在 setContentView() 方法内部被设置为 true,这样再调用 requestWindowFeature() 就会引发错误。

因此,正确的顺序是先调用 requestWindowFeature() 请求窗口功能,然后再调用 setContentView() 设置布局内容。这样可以避免错误发生,并正确启用所需的窗口功能。

为什么这么设计呢?

Android 中的窗口布局是通过 DecorView 来实现的。DecorView 是一个表示活动窗口所有内容的根视图,包括标题栏、内容区域和其他装饰元素。

requestWindowFeature() 方法的设计是为了在创建 DecorView 之前设置窗口的特征。这样可以确保在创建活动窗口时,根据特征的设置来决定如何绘制窗口的外观和行为。

当调用 setContentView() 方法时,将会创建 DecorView 和添加内容区域。在这之前,系统需要知道要使用哪些窗口特征来决定如何绘制 DecorView。这就是为什么应该在调用 setContentView() 之前先调用 requestWindowFeature() 的原因。

通过在 requestWindowFeature() 中设置特征,我们可以控制窗口的外观和功能,例如是否显示标题栏、进度条等。这种设计方式使得我们能够在活动加载布局之前对窗口进行必要的配置

为什么 requestWindowFeature(Window.FEATURE_NO_TITLE);设置无效?

requestWindowFeature(Window.FEATURE_NO_TITLE) 设置无效的原因是因为你的活动继承自 AppCompatActivity,而不是直接继承自 Activity。在 AppCompatActivity 中,标题栏的处理方式不同于传统的 Activity。

在 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)。前者会确保正确处理标题栏的隐藏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/786275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小白必看系列之图书管理系统-登录和注册功能示例代码

文章目录 前言变量定义区域实体部分区域注册账号逻辑用户登录逻辑退出程序打印用户信息完整代码完结 前言 在现代社会中,计算机科学和编程技术的重要性日益凸显。作为开发者和技术爱好者,我们时刻追求着创新和实用性,希望通过技术的力量改善…

Springboot+Netty

目录 一、netty入门 二、启动方式 三、netty服务启动类 四、handler链 五、具体业务 六、 线程或者非spring管理的bean中获取spring管理的bean 七、效果 一、netty入门 Netty-导学_哔哩哔哩_bilibili 入门视频量比较大,最主要是了解netty的架构 netty官网&am…

Chapter 9 Port Delays (端口延迟)set input/output delay

文章目录 9.1 Input Availability---输入有效9.1.1 Min and Max Availability Time---最小和最大有效时间9.1.2 Multiple Clocks9.1.3 Understanding Input Arrival Time 9.2 Output Requirement9.2.1 Min and Max Required Time9.2.2 Multiple Reference Events9.2.3 Understa…

【梦辛工作室】IF判断优化、责任链模式 IfChain

大家好哇,我是梦辛工作室的灵,在最近的开发中,有许多需要判断的分支处理,且处理内容较多且复杂,代码就容易越写越复杂,导致后期无法继续更新跌打,然后基于这个环境,我用责任链模式写…

热备盘激活失败导致raid5阵列崩溃的服务器数据恢复案例

服务器数据恢复环境: 一台Linux Redhat操作系统服务器上有一组由5块硬盘组建的raid5阵列,包含一块热备盘。上层部署一个OA系统和Oracle数据库。 服务器故障: raid5阵列中的1块磁盘离线,硬盘离线却没有激活热备盘,直到…

系统集成|第四章(笔记)

目录 第四章 项目管理一般知识4.1 项目与项目管理4.1.1 项目4.1.2 项目的组织4.1.3 项目生命周期4.1.4 典型的信息系统项目的生命周期模型4.1.5 单个项目管理过程 上篇:第三章、系统集成专业技术 第四章 项目管理一般知识 4.1 项目与项目管理 4.1.1 项目 定义&…

SQL注入实操二

文章目录 一、sqli-lab靶场1.轮子模式总结2.Less-21a.注入点判断b.轮子测试c.获取数据库名称d.获取表信息e.获取列信息f.获取表内数据 3.Less-22a.注入点判断b.轮子测试c.获取数据库名称d.获取表信息e.获取列信息f.获取表内数据 4.Less-23a.注入点判断b.轮子测试c.获取数据库名…

如何模拟实现分布式文件存储

如何解决海量数据存不下的问题 传统做法是是在宕机存储。但随着数据变多,会遇到存储瓶颈 单机纵向扩展:内存不够加内存,磁盘不够家磁盘。有上限限制,不能无限制加下去 多机横向扩展:采用多台机器存储,一…

vue+axios实现点击取消请求功能

代码片段 <template> <el-button type"primary" click"clickExportData">导出</el-button><el-dialog title"正在导出&#xff0c;请稍等" :visible.sync"progressShow" :close-on-click-modal"false"…

sql优化:为什么通常选用根据id查询而不是根据name?

先来看一个最常见的问题,下面两个sql语句哪个效率更高一些&#xff1f; select * from user where id 1; select * from user where name 张三 在没有给name加索引的时候&#xff0c;id是有主键索引的&#xff0c;也就是聚集索引&#xff0c;这样就是一个BTree结构&#xf…

成为一名数字IC后端工程师需要掌握哪些技能?(内附学习视频)

众所周知&#xff0c;数字后端设计是IC设计中必不可少的一个环节&#xff0c;数字后端工程师是将门级网表转换成标准的GDS文件&#xff0c;又称为设计实现或物理设计。正所谓前端保证功能正确&#xff0c;后端保证芯片的实现正确。 数字后端工程师是做什么的&#xff1f; 数字…

操作系统启动相关概念(BIOS、MBR、GPT、BRUB)

不管是 Windows 还是 Linux 操作系统&#xff0c;底层设备一般均为物理硬件&#xff0c;操作系统启动之前会对硬件进行检测&#xff0c;然后硬盘引导启动操作系统&#xff0c;如下为操作系统启动相关的各个概念。 一、BIOS 基本输入输出系统&#xff08;Basic Input Output Sy…

android studio(火烈鸟版本)使用protobuf

一、简介 Protobuf 全称&#xff1a;Protocol Buffers&#xff0c;是 Google 推出的一种与平台无关、语言无关、可扩展的轻便高效的序列化数据存储格式&#xff0c;类似于我们常用的 xml 和 json。 二、特点 Protobuf 用两个字总结&#xff1a;小&#xff0c;快。用 Protobu…

PS 裁剪工具及工具栏配置讲解

我们还是日常打开PS软件 首先 我们右侧菜单中右键 找到裁剪工具组 当我们选择裁剪工具时 图像边上会出现一个白色的框框 用法比较简单 我们可以鼠标拖住一个边 然后 往里拖动 将不要的东西剪掉 然后 鼠标双击 即可保存结果 然后 我这里撤回一下 这些部分还有用 还有一个…

安装nvm管理node

1.首先卸载已存在的node cmd输入node提示&#xff1a;‘node’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 2.安装nvm 安装地址 &#xff1a;Releases coreybutler/nvm-windows GitHub 本人选择1.1.7 输入nvm打印出了nvm的指令列表&#xff0c;说明…

【Nodejs】原生nodejs路由、获取参数、静态目录

1.路由 index.js // 启动服务 const server require(./server.js); //路由模块 const route require(./route.js); //api const apiRouter require(./api.js);server.use(route); server.use(apiRouter); server.start();server.js const http require(http);//创建一个大…

“解锁高效水资源管理:灌区管理系统一图详解“

平台概述 柳林灌区管理系统平台以物理灌区为单元、时空数据为底座、数学模型为核心、水利知识为驱动&#xff0c;对物理灌区全要素和建设运行全过程进行数字映射、智能模拟、前瞻预演&#xff0c;与物理灌区同步仿真运行、虚实交互、迭代优化&#xff0c;实现对物理灌区的实时…

ChatGPT和搜索引擎哪个更好用

目录 ChatGPT和搜索引擎的概念 ChatGPT和搜索引擎的作用 ChatGPT的作用 搜索引擎的作用 ChatGPT和搜索引擎哪个更好用 总结 ChatGPT和搜索引擎的概念 ChatGPT是一种基于对话的人工智能技术&#xff0c;而搜索引擎则是一种用于在互联网上查找和检索信息的工具。它们各自具…

脑电信号处理与特征提取——2.脑电的神经起源与测量(夏晓磊)

目录 二、脑电的神经起源与测量 2.1 脑电的神经起源 2.2 脑电的测量 二、脑电的神经起源与测量 2.1 脑电的神经起源 脑电起源于大脑皮层大量神经元的同步突触活动&#xff0c;主要贡献来自锥体细胞。 静息电位&#xff1a;内负外正&#xff0c;K内流。 动作电位&…

stm8s003_切换时钟流程分析、配置外部晶振(库函数调用)

1、stm8s003的时钟 复位后&#xff0c;默认使用内部高速时钟HSI&#xff08;16MHz&#xff09;的8分频&#xff0c;也就是2MHz. 代码开始运行&#xff0c;也就是运行到main函数&#xff0c;我们就可以修改时钟源为外部晶振。 2、切换时钟流程分析&#xff0c;参考官方应用手册…