安卓setContentView

2023-05-16

首先进入activity中找到setContentView方法:

public void setContentView(@LayoutRes int layoutResID) {
     getWindow().setContentView(layoutResID);
     initWindowDecorActionBar();
}

找到三个setContentView方法,我们发现内部都是调用getWindow()的setContentView方法,getWindow()得到一个在Activity的attach方法中初始化的PhoneWindow对象mWindow

进入PhoneWindow类可知,该类继承Window类,Window类是抽象类,注释如下

/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
 * window manager. It provides standard UI policies such as a background, title
 * area, default key processing, etc.
 *
 * <p>The only existing implementation of this abstract class is
 * android.view.PhoneWindow, which you should instantiate when needing a
 * Window.
 */
 public class PhoneWindow extends Window implements MenuBuilder.Callback {

百度翻译:顶级视图和行为策略的基础抽象类。此类的实例被用做顶级视图添加到window manager中。提供了UI策略规则,如背景background、title区域、默认key处理等
该抽象类存在的唯一的实现是android.view.PhoneWindow,当你需要一个window的时候可以用到它。

在这里插入图片描述
每个Activity持有一个Window对象,也就是PhoneWindow,PhoneWindow又持有了一个DecorView对象,DecorView对象所加载的布局资源中含有TextView(R.id.title)和FrameLayout(R.id.content)

回到PhoneWindow中,找到setContentView方法

@Override
public void setContentView(int layoutResID) {

	if (mContentParent == null) {
		installDecor();
	} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
		mContentParent.removeAllViews();
	}
	if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
		final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
		getContext());
		transitionTo(newScene);
	} else {
	//将layoutResID解析后添加到mContentParent的子view树里
	mLayoutInflater.inflate(layoutResID, mContentParent);
	}
    	...
    	...
    	...
}

首先来看mContentParent

ViewGroup mContentParent;

mContentParent 是被放置在window窗口的视图,可能是mDecor 本身,或者是mDecor 的子视图

private DecorView mDecor;

DecorView 是window窗口顶级视图,包含窗口装饰
当mContentParent == null时执行installDecor()方法

private void installDecor() {
		...
	if (mDecor == null) {
		//不存在,创建
		mDecor = generateDecor(-1);
         ...
	} else {
		//存在,将此PhoneWindow传递给mDecor
		mDecor.setWindow(this);
	}
	if (mContentParent == null) {
		//创建基础试图框架mContentParent ,并在其中为mDecor设置布局资源
		mContentParent = generateLayout(mDecor);
			...
		//decor_content_parent是基础布局中最外层布局的id,其中的根布局ActionBarOverlayLayout
		//实现了DecorContentParent 接口
		final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
			R.id.decor_content_parent);
		if (decorContentParent != null) {
		mDecorContentParent = decorContentParent;
		//设置Window的一些回调、title等
		mDecorContentParent.setWindowCallback(getCallback());
           		 ...
           		 ...
         	  	 ...
		} else {
			//设置title,根据FEATURE_NO_TITLE设置是否显示
			mTitleView = findViewById(R.id.title);
			if (mTitleView != null) {
			if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
				final View titleContainer = findViewById(R.id.title_container);
					if (titleContainer != null) {
						titleContainer.setVisibility(View.GONE);
					} else {
						mTitleView.setVisibility(View.GONE);
					}
				mContentParent.setForeground(null);
			} else {
				mTitleView.setText(mTitle);
			}
		}
	}

	if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
		mDecor.setBackgroundFallback(mBackgroundFallbackResource);
	}
           ...........
}

现在可知installDecor方法的作用有两点:
一、将PhoneWindow绑定给DecorView;
二、调用generateLayout方法.

protected DecorView generateLayout(DecorView decor) {
			...
			...
		//根据activity是否设置ActionBar,为layoutResource赋值不同布局screen_action_bar或者screen_title
		//screen_action_bar内部包含R.id.content(Framelayout)和一个ActionBarContainer布局
		//screen_title内部包含R.id.content(Framelayout)和一个被Framelayout包裹的R.id.title(TextView)
		} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
			layoutResource = a.getResourceId(
			R.styleable.Window_windowActionBarFullscreenDecorLayout,
				R.layout.screen_action_bar);
		} else {
			layoutResource = R.layout.screen_title;
		}
            ...
            ...
		//为mDecor加载布局资源layoutResource
		mDecor.startChanging();
		mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
       		 
		//contentParent 获取该布局中的R.id.conten(FrameLayout)
		ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
		if (contentParent == null) {
			throw new RuntimeException("Window couldn't find content container view");
		}
       		 ...
       		 ...
		//将mDecor布局中的R.id.conten(FrameLayout)作为基础布局框架返回
		return contentParent;
}

generateLayout方法的主要作用
1、创建基础视图框架布局mContentParent ;
2、对mDecor加载资源布局。
其中mContentParent 是mDecor布局中的子view(R.id.content)

在setContentView方法中执行完installDecor方法后会执行mLayoutInflater.inflate(layoutResID, mContentParent);将传递进来的layoutResID布局资源解析添加到mContentParent (com.android.internal.R.id.content)的子view树里,到这里就完成了setContentView方法的布局加载。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

安卓setContentView 的相关文章

  • Jenkins自动部署,mvn不同的环境打包配置

    今天看了个问题 xff0c 就是在Jenkins里如何根据不同的环境发布代码 我本地的代码环境有 xff0c 开发环境 测试环境 预发布环境和线上环境 基于项目的风险控制 xff0c 安全控制 xff0c 我只有开发环境和测试环境的权限 x
  • IOException while sending message; nested exception is:java.io.FileNotFoundException

    异步发送邮件出现的异常情况 1 问题描述 近期做了一个发送邮件的功能 xff0c 因为在处理发送邮件联系人上出现过失效的邮箱地址 xff0c 为了快速定位到问题 现将批量发送的方式改为单独发送 Failed messages javax m
  • 自定义分页

    给大家介绍一个简单分页的方法 xff08 有兴趣的可以自己试一下 xff09 1 实体 package com hffss entity ext import lombok Builder import lombok Data import
  • SpringBoot请求体中的流只能读取一次的问题HttpServletRequest的流只能读取一次的原因

    问题场景 xff1a 在项目开发过程中需要记录用户的操作行为 xff0c 即用户请求的url和相关url中带有的请求体参数 xff0c 在springboot中只能在拦截器中读取了一次 xff0c 在controller获取不到参数 经过代
  • @PostConstruct注解

    64 PostConstruct 64 PostConstruct注解好多人以为是Spring提供的 xff0c 其实是Java自己的注解 Java中该注解的说明 xff1a 64 PostConstruct该注解被用来修饰一个非静态的vo
  • 天线长度计算

    首先 xff0c 理想天线的长度是半波长 平时说的四分之一波长天线 xff0c 实际上需要考虑 地 才能构成完整的天线 xff0c 也就是我们常说的 非平衡天线 xff1b 天线本身只是天线的一部分 天线长度是波长的四分之一 波长 61 光
  • NFS服务配置、搭建、应用

    一 NFS服务 1 NFS服务只能部署到linux环境而不适用于windows环境 xff0c 说白了就是让不同的机器 不同的系统可以共享彼此的文件 xff08 例如 xff1a windows的共享磁盘一样 xff09 2 NFS原理流程
  • Java 调用Shell脚本执行 SCP命令提示Authorized users only. All activity may be monitored and reported.

    近期做了个小项目主要是关于数据处理这方面的 在Java后端调用服务器上Shell脚本 xff0c 而Shell脚本执行时一条Scp执行结果的提示报 Authorized users only All activity may be moni
  • Java 调用Http和Https接口

    Java调用Http接口和Https接口 大多数我们调用的接口都是Http的 xff0c 很少有Https的接口 xff0c 近期做了个项目就用到和Https接口的请求调用 xff0c 和大家分享一下心得 Http接口和Https接口主要是
  • 多种方式查看电脑是否支持Modern Standby

    控制台查看 CMD输入powercfg a 显示如下有S0 xff0c 则支持Modern Standby 注册表查看 Win 43 R 输入regedit进入注册表 xff0c 查看HKEY LOCAL MACHINE SYSTEM Cu
  • Javaer,你必须要了解的ExecutorService

    ExecutorService初接触 之前做的一个功能里有一个耗时操作 xff1a 处理数据库里对应的记录 xff0c 然后将每个处理后的结果做个排序 恕本人小白 xff0c 刚开始直接用单线程处理 xff01 你敢信 xff1f xff0
  • centos 6.4 卡在了进度条界面

    1 从新启动 reboot 在进度条界面时按住F5 xff0c 可以看到启动过程 xff0c 定位到starting certmonger卡住了 原因分析 xff1a X11图形化界面服务引起的 xff0c 导致开机无法进入图形化界面 用x
  • Dockerfile 构建镜像时所遇到的问题

    1 vim Dockerfile dockerfile的内容如下 xff1a FROM ubuntu RUN apt get update amp amp apt install y nginx CMD 34 usr sbin nginx

随机推荐