博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 从SetContentView()谈起
阅读量:5926 次
发布时间:2019-06-19

本文共 4294 字,大约阅读时间需要 14 分钟。

当我们新建一个工程的时候,选择生成一个Activity,AS会自动给我们生成一个界面,那么这个界面是怎么生成的呢,下面我们就来分析一下:

Activity中的代码:

@Overrideprotected void onCreate(Bundle savedInstanceState) {              super.onCreate(savedInstanceState);              setContentView(R.layout.activity_main);}复制代码

XML中的代码:

复制代码

用Hierarchy viewer工具来查看一下结构图: ![@P8]6~ZC7~MJ~LJFG(DPBWA.png](http://upload-images.jianshu.io/upload_images/587163-e85daee233003243.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

DecorView以及它的子View一目了然,先看下SetContentView()的实现:

@Overridepublic void setContentView(int layoutResID) {     // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window    // decor, when theme attributes and the like are crystalized. Do not check the feature    // before this happens.    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 {        mLayoutInflater.inflate(layoutResID, mContentParent);    }    mContentParent.requestApplyInsets();    final Callback cb = getCallback();    if (cb != null && !isDestroyed()) {        cb.onContentChanged();    }}复制代码
// This is the top-level view of the window, containing the window decor.private DecorView mDecor;// This is the view in which the window contents are placed. It is either// mDecor itself, or a child of mDecor where the contents go.//mContentParent 是放置窗体内容的容器,也就是我们 setContentView() //时所加入的 View 视图树private ViewGroup mContentParent;复制代码

DecorView是PhoneWindow的一个内部类,同时DecorView也是Activiy的顶级View,一般来说DecorView的内部包括导航栏(NavigationBar)和状态栏(StatusBar),但这个会随着主题的变化而发生改变。刚开始mContentParent的值是null,所以会走installDecor():

if (mDecor == null) {      mDecor = generateDecor();    mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);    mDecor.setIsRootNamespace(true);  if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {        mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);      }}if (mContentParent == null) {    mContentParent = generateLayout(mDecor);    // Set up decor part of UI to ignore fitsSystemWindows if appropriate.      mDecor.makeOptionalFitsSystemWindows();     final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(R.id.decor_content_parent);复制代码
protected DecorView generateDecor() {    return new DecorView(getContext(), -1);}复制代码

在installDecor()里面通过调用generateDecor()方法来初始化DecorView,此时DecorView什么都没有,只是一个空的FrameLayout,往下走,来到generateLayout(mDecor),跳过一些主题布局设置,直接来到关键代码:

mDecor.startChanging();View in = mLayoutInflater.inflate(layoutResource, null);decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));mContentRoot = (ViewGroup) in;ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);if (contentParent == null) {    throw new RuntimeException("Window couldn't find content container view");}复制代码
/** * The ID that the main layout in the XML layout file should have. */public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;复制代码

DecorView通过generateLayout(mDecor)加载到具体的布局文件,具体的布局文件和系统版本以及主题有关,ID_ANDROID_CONTENT对应的即是R.id.content,也是我们通过SetContentView()中设置的布局id,走完installDecor(),我们继续看PhoneWindow中的SetContentView()方法,

if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {    final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,getContext());    transitionTo(newScene); } else {    mLayoutInflater.inflate(layoutResID, mContentParent); }复制代码

接下来就简单了,mLayoutInflater.inflate(layoutResID, mContentParent),因为前面通过installDecor()创建了DecorView,因此这一步就是将Activity的布局(layoutResID)添加到mContentParent中了,到这里为止,Activity的布局文件就已经添加到DecorView里面了,继续看SetcontentView():

mContentParent.requestApplyInsets();final Callback cb = getCallback();if (cb != null && !isDestroyed()) {    cb.onContentChanged();}复制代码

由于Activity实现了Window的Callback接口,

并且Activity的布局文件已经添加到DecorView里的mContentParent里了,当执行cb.onContentChanged()后,Activity就会回调onContentChanged()方法,由于Activity的onContentChanged()是个空实现,我们可以在子Activity中处理这个回调处理相应逻辑,到这里为止DecorView就已经被创建并初始化完毕。

转载于:https://juejin.im/post/5a33e7fd6fb9a0452341f3b8

你可能感兴趣的文章
在Esxi 5.1虚机中安装OEM服务器系统
查看>>
CentOS 安装NTFS-3G,让系统支持NTFS分区的方法
查看>>
linux samba服务器
查看>>
Python统计列表中的重复项出现的次数的方法
查看>>
为什么Docker是云计算必然的现在和未来
查看>>
centos7 kickstart 使用小结
查看>>
32.find命令
查看>>
tomcat两个项目冲突
查看>>
AUTH password
查看>>
hadoop-2.7.1+zookeeper-3.4.8+hbase-1.2.1+apache-hive-2.0.0完全分布式集群
查看>>
KVM 虚拟机自动克隆脚本
查看>>
构建微型数据中心——在laptop上运行Rancher
查看>>
3月6日云栖精选夜读:如何实现32.5万笔/秒的交易峰值?阿里交易系统TMF2.0技术揭秘...
查看>>
将VNC 安装在Centos 7步骤
查看>>
计算机与操作系统基础小结
查看>>
RabbitMQ详解(三)
查看>>
Oracle 12c应用连接VIP轮训负载均衡?
查看>>
Docker Network 配置,自定义bridge网络
查看>>
tomcat
查看>>
时任上海来伊份互联网事业群总裁王戈钧 :传统企业(线上+线下)移动互联网改造...
查看>>