1.引言

最近准备重新学习下Android,加深理解,快速形成自己的知识结构体系。最先学习的就算View部分,从自定义View到Activty层次结构,到layout加载过程。等等都会看一遍,在此记录下Layout的加载过程

2.正题

2.1 Activity的流程加载

Activity类中setContentView 追踪(善于用bookMark)

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

追踪代码,PhoneWindow的setContentView方法:

image.png

mLayoutInflater.inflate(layoutResId,mContentParent)

由代码片段可以看出来:layoutResId的父布局就是mContentParent。那么mContentParent究竟是什么呢?

我们知道DecorView 包括TitleView +ContentView.

image.png

追踪代码:installDescor():

image.png

generateLayout()方法:

protected ViewGroup generateLayout(DecorView decor) { // Apply data from current theme. // 获得窗体的 style 样式 TypedArray a = getWindowStyle(); // 省略大量无关代码 // Inflate the window decor. int layoutResource; int features = getLocalFeatures(); //填充带有 style 和 feature 属性的 layoutResource (是一个layout id) View in = mLayoutInflater.inflate(layoutResource, null); // 插入的顶层布局 DecorView 中 decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); mContentRoot = (ViewGroup) in; // 找到我们XML文件的父布局 contentParent ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); if (contentParent == null) { throw new RuntimeException("Window couldn't find content container view"); } // 省略无关代码 mDecor.finishChanging(); // 返回 contentParent 并赋值给成员变量 mContentParent return contentParent; } 

给DecorView添加一个名字为mContentRoot的view。并且mContentRoot里面包含了一个id为ID_ANDROID_CONTENT的 mContentParent.

得到了mContentParent之后,在根据mLayoutInflater.inflate(layoutResId,mContentParent) 就将Layout布局加载进了DecorView,然后这个视图才能被我们看到。

验证:

image.png

说明了mContentParent是FramLayout

3.AppCompatActivity 加载View得过程

  @Overridepublic void setContentView(@LayoutRes int layoutResID) { getDelegate().setContentView(layoutResID); } 

getDelegate():

    @NonNullpublic AppCompatDelegate getDelegate() { if (mDelegate == null) { mDelegate = AppCompatDelegate.create(this, this); } return mDelegate; } 

跟踪create()方法,

  public static AppCompatDelegate create(Activity activity, AppCompatCallback callback) { return create(activity, activity.getWindow(), callback); } 

activity.getWindow() 由上面可知,得到的肯定是PhoneWindow。问题来了,activity这个时候真的能得到一个非null的PhoneWindow吗?。发现在activity调用attach方法的时候就会初始化PhoneWindow:

 final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) { attachBaseContext(context); mFragments.attachHost(null /*parent*/); mWindow = new PhoneWindow(this, window, activityConfigCallback); mWindow.setWindowControllerCallback(this); ...... } 

Activity.attach是在performLaunchActivity中本调用,也就是在ActivityThread中被调用。所以在Activity中任何时候getWindow(),都能得到PhoneWindow。

继续跟踪代码:
create方法调用的是:

 private static AppCompatDelegate create(Context context, Window window, AppCompatCallback callback) { if (Build.VERSION.SDK_INT >= 24) { return new AppCompatDelegateImplN(context, window, callback); } else if (Build.VERSION.SDK_INT >= 23) { return new AppCompatDelegateImplV23(context, window, callback); } else if (Build.VERSION.SDK_INT >= 14) { return new AppCompatDelegateImplV14(context, window, callback); } else if (Build.VERSION.SDK_INT >= 11) { return new AppCompatDelegateImplV11(context, window, callback); } else { return new AppCompatDelegateImplV9(context, window, callback); } } 

setContentView 是在AppCompatDelegateImplV9类中被重写,也就是说最终是调用AppCompatDelegateImplV9.setContentView();

  @Overridepublic void setContentView(int resId) { ensureSubDecor(); ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content); contentParent.removeAllViews(); LayoutInflater.from(mContext).inflate(resId, contentParent); mOriginalWindowCallback.onContentChanged(); } 
  ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);

很容易让我们想到mSubDecor 是不是等同于上文中的mContentRoot 呢?

看看ensureSubDecor怎么写的:

 if (mOverlayActionMode) {subDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple_overlay_action_mode, null);} else {subDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple, null); } 

subDecor 是系统提供的ViewGroup 里面有一个android.R.id.content布局,和mContentRoot 作用一模一样。

基本上分析到此结束,也是比较简单。

Android View之布局加载流程相关推荐

  1. android Q launcher 数据加载流程

    时间:2020/08/24 之前公司不允许csdn,笔记写在其它地方.最近整理过来 下一篇:launcher数据加载(二) 前言 androidQ和androidP上Launcher结构有很大区别. ...

  2. Android SIM卡识别加载流程

    文章目录 总述 代码路径 UICC框架 SIM卡识别加载流程 日志分析举例 总述 本文基于Android N(Android 7) 首先要知道SIM卡一般是挂载在CP侧(MODEM侧)的,由MODEM ...

  3. Launcher布局加载流程

    前言 以前只知道Launcher是桌面,也就是显示已安装的应用图标,其它的一概不知.当自己要去学习它,要去修改它时,却发现Launcher涉及到的东西很多,此次则将自己对Launcher布局的理解做个 ...

  4. Android 13 平板Taskbar加载流程

    从 Android 12开始,如果是大屏底下导航栏会变成显示一个任务栏,从 NavigationBar 变成 Taskbar . 注:CentralSurfacesImpl.java 与 原来的 st ...

  5. Android SIM 卡信息加载流程

    在PhoneAPP启动关系类初始化中,我们提到监听处理SIM卡状态的两个关键类UiccController和IccCardProxy UiccController:整个UICC事务处理的入口,负责对外 ...

  6. android系统加载主题的流程,详解Android布局加载流程源码

    一.首先看布局层次 看这么几张图 我们会发现DecorView里面包裹的内容可能会随着不同的情况而变化,但是在Decor之前的层次关系都是固定的.即Activity包裹PhoneWindow,Phon ...

  7. Android系统字体加载流程

    一.背景 视觉同学提了一个需求,要求手机中显示的字体可以支持medium字体,经过分析,android原生的字体库中并没有中文的medium字体,如果使用bold,显示又太粗,为满足需求,需要分析an ...

  8. 【Android 应用开发】UI绘制流程 ( 生命周期机制 | 布局加载机制 | UI 绘制流程 | 布局测量 | 布局摆放 | 组件绘制 | 瀑布流布局案例 )

    文章目录 一. 博客相关资料 及 下载地址 1. 代码查看方法 ( ① 直接获取代码 | ② JAR 包替换 ) 2. 本博客涉及到的源码查看说明 二. Activity 生命周期回调机制 1. An ...

  9. android 图片横竖判断_Android横竖屏切换及其对应布局加载问题详解

    本文为大家分享了Android横竖屏切换及其对应布局加载问题,供大家参考,具体内容如下 第一,横竖屏切换连带横竖屏布局问题: 如果要让软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同 ...

  10. Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%

    系列文章 前言 在Android布局优化(一)从布局加载原理说起中我们说到了布局加载的两大性能瓶颈,通过IO操作将XML加载到内存中并进行解析和通过反射创建View.这里介绍一种避免运行时通过IO操作 ...

最新文章

  1. 赛门铁克公告:解密Kneber恶意软件
  2. [Robot Framework] 怎么做数学运算?
  3. 在墙上找垂直线_墙上如何快速找水平线
  4. 想深度探究数据库内核技术,墙裂推荐你看看这个
  5. python 并发编程目录
  6. powerbi python词云图_使用Power BI制作可爱的词云图
  7. [转载]JSONP跨域的原理解析
  8. C#获取C# DLL中的指定接口的所有实现实例 - qq_19759475的博客 - CSDN博客
  9. 计算机删除文件的原理,三个简单步骤,马上恢复被永久删除的文件
  10. 四色定理java_java – 四色定理的递归算法
  11. Microsoft Edge浏览器上不了网,其他浏览器可以
  12. 引进国外SD-WAN技术,凌锐蓝信为企业提供跨境网络连接服务
  13. telegram群组管理机器人
  14. itext将html转换为pdf,使用itext将html转换为pdf
  15. 高通滤波器与低通滤波器
  16. micropython实现mpy的ota(有用,推荐)
  17. vue-router路由模式有几种?
  18. iOS 引导图的聚光灯效果代码实现
  19. 信息学奥赛一本通-1047
  20. 感悟西游记——成气候的妖精都是领导家的

热门文章

  1. Atitit atiuse软件系列
  2. Atitit. Ati IDE 开发平台的第一版规划
  3. paip.自适应网页设计 跟 响应式 设计的区别跟原理and实践总结
  4. paip.日期时间操作以及时间戳uapi php java python 总结
  5. paip.mysql 性能测试by mysqlslap
  6. paip.sql2k,sql2005,sql2008,sql2008 r2,SQL2012以及EXPRESS版本的区别
  7. (转)对冲基金投身“另类数据”淘金热
  8. Julia:从交易流水动态计算可用资金
  9. 【优化调度】基于matlab粒子群算法求解经济调度优化问题【含Matlab源码 1489期】
  10. 【优化求解】基于matlab GUI模拟退火算法区域通信网频率规划【含Matlab源码 933期】