| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android中的LayoutInflater分析(二) -> 正文阅读 |
|
[移动开发]Android中的LayoutInflater分析(二) |
文章收藏的好句子:好好提升自己,以后人生路上就少一些尴尬,尴尬到来的前几年,其实我们有机会避免的,不要得过且过。 ps:本篇文章是基于 Android Api 26 来分析的 目录 1、LayoutInflater 创建 View 过程 ? ? ?1、1?LayoutInflater?的?rInflate(该方法有5个参数)?方法分析 ? ? ?1、2?LayoutInflater?的?parseInclude(该方法有4个参数)?方法分析 ? ? ?1、3?LayoutInflater 的?createViewFromTag 方法分析 1、LayoutInflater 创建 View 过程 1、1?LayoutInflater?的?rInflate(该方法有5个参数)?方法分析 我们接着Android中的LayoutInflater分析(一)这篇文章继续分析,我们看回 LayoutInflater 的 inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)?;
还记得前一篇文章Android中的LayoutInflater分析(一)所说的吗?注释18 的代码和注释23 的代码本质上都是解析子标签,只是参数不一样而已,都是调用 LayoutInflater 的 rInflate(XmlPullParser parser, View parent, Context context,AttributeSet attrs, boolean finishInflate) 方法,看注释18 方法的第二个参数 root 和?注释23 方法的第二个参数 temp 是不一样的,当要解析的 xml 文件的开始标签是 merge 时,根标签就是 root,当要解析的?xml 文件的开始标签不是?merge?时,根标签就是 temp;看注释18?方法的第五个参数?root 和?注释23?方法的第四个参数?temp?是不一样的,为?true 时,表示要回调父元素(父元素是 ViewGroup 或者继承于 ViewGroup)的?onFinishInflate 方法,root 作为参数之一,在?LayoutInflater 的 inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)?方法被调用之前早就创建好了,所以?root?的?onFinishInflate 方法早就被调用过了,所以注释18 的方法的第五个参数为 false,temp?是在?LayoutInflater 的 inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)?方法调用的过程中创建的,才刚创建好?temp,所以 temp 的?onFinishInflate 方法还没被调用过,所以注释23 方法的第四个参数为 true。 我们看一下?LayoutInflater 的?rInflate(XmlPullParser parser, View parent, Context context,AttributeSet attrs, boolean finishInflate)?方法;
看注释30 的代码,判断解析的标签是是否 include;注释31 的代码,判断解析的当前标签的深度是否为0,也就是当前标签是否有父标签,如果深度为0表示没有父标签,那么就会抛出异常,因为 include 标签不可以作为一个 xml 文件的根标签,这个大家都知道的;注释32 的代码是具体解析 include 标签的方法,后面再说;我们知道?LayoutInflater 的?rInflate(XmlPullParser parser, View parent, Context context,At-tributeSet attrs, boolean finishInflate)?方法是解析子标签用的,看注释33 的代码,如果子标签为 merge,那么就抛出异常;看注释34 的代码,finishInflate 为 true,就会调用 ViewGroup(只要是父标签,那么它一定是 ViewGroup,这个不用怀疑的)?的 onFinishInflate 方法,这篇文章的上面有说的。 1、2?LayoutInflater?的?parseInclude(该方法有4个参数)?方法分析 我们看回注释32 的代码,也就是 LayoutInflater 的 parseInclude(XmlPullParser parser, Context context, View parent,AttributeSet attrs)?方法;
注释35 的代码表示提取出 include 的 thme 属性,如果设置了 them 属性,那么 include 包裹的 View 设置的 theme 无效;注释36 的代码表示通过 include 标签的 layout 属性获取到一个?子布局 xml 文件的 id;注释37 的代码,如果 layout 的 id 为0,证明没有给 include 标签设置 layout 属性,那么就会抛出异常;注释38 的代码表示通过子布局 xml 的 id 创建一个 XmlResourceParser 对象;看注释39 的代码,如果子布局 xml 文件的根标签是 merge,那么又调用到 LayoutInflater 的 rInflate(XmlPullParser parser, View parent, Context context,AttributeSet attrs, boolean finishInflate)?方法,这样就通过 LayoutInflater 的 rInflate(XmlPullParser parser, View parent, Context context,AttributeSet attrs, boolean finishInflate)?方法进行不停的解析标签。 1、3?LayoutInflater?的?createViewFromTag 方法分析 好了,上面说了解析标签的过程,这里我们分析一下 View 的创建过程,看回注释19 的代码,也就是 LayoutInflater 的 createViewFromTag(View parent, String name, Context context, AttributeSet attrs)?方法看起; 看注释40 的代码,LayoutInflater 的 createViewFromTag(View parent, String name, Context context, AttributeSet attrs)?方法又调用了 LayoutInflater 的?createViewFromTag(View parent, String name, Context context, AttributeSet attrs,boolean ignoreThemeAttr)?方法;
注释42、43、44、45?的代码我就不分析了,我分析的是一个呈现界面的类直接继承 AppCompatActivity 而不是直接继承 Activity,所以最终会走注释41 的代码,mFactory2?对象的实现类到底是什么,可以看Android中的AppCompatActivity的偷梁换柱之UI偷换这篇文章,Android中的AppCompatActivity的偷梁换柱之UI偷换拿的是 AppCompatDelegateI-mplV9 来分析,而我们用的是 API 26 的来分析,拿的是 AppCompatDelegateImplN 来分析,那岂不是不一样吗?其实它们实例化并赋值给?mFactory2 的过程是一样的,AppCompatDelegateImplN?间接继承于?AppCompatDelegateImplV9,而且?AppCompatDelegateImp-lN?也没有重写?onCreateView(View parent, String name, Context context, AttributeSet attrs) 方法,onCreateView(View parent, String name, Context context, AttributeSet attrs)?方法仍然在?AppCompatDelegateI-mplV9 中实现;注意这里我分析的是用 Activity 为上下文创建 View 的思路,别搞错了,为了防止搞混淆,我列举一下用?Activity 为上下文创建?View 的代码;
注释46 中的?LayoutInflater.from(activity)?代码最终会调用到?Activity 的 PhoneLayoutInflater?对象中的 cloneInContext(Context newContext)方法,可以看Android中的LayoutInflater分析(一)这篇文章追踪一下,然后通过 Activity 的?PhoneLayoutInflater?对象的?cloneInContext(Co-ntext newContext) 方法构建一个新的?PhoneLayoutInflater?对象并将?Activity?的?PhoneLayoutInflater 对象中的?mFactory2?赋值给新的?PhoneLayoutInflater?中的?mFactory2。 我们看回注释41 if 语句下的代码,也就是?AppCompatDelegateImplV9 的 onCreateView(View parent, String name, Context context, AttributeSet attrs)?方法; 看注释47 的代码,AppCompatDelegateImplV9?的 onCreateView(Vie-w parent, String name, Context context, AttributeSet attrs)?方法又调用?AppCompatDelegateImplV9?的 createView(View parent, final String name, @NonNull Context context,@NonNull AttributeSet attrs)?方法;
看注释48 的代码,mAppCompatViewInflater 是?AppCompatViewInfla-ter 类型的对象,这里又调用?AppCompatViewInflater?的?createView(View parent, final String name, @NonNull Context context,@NonNull AttributeSet attrs, boolean inheritContext,boolean readAndroidTheme, boolean readAppTheme, boolean wrapContext) 方法;
看注释49 的代码,如果是系统的标签,那么直接通过 new 关键字创建一个 View 对象;如果不是系统标签,那么就走注释50 的代码,也就是?AppCo-mpatViewInflater 的?createViewFromTag(Context context, String name, AttributeSet attrs) 方法;
注释52 的代码通过自定义的标签创建 View,第3个参数 null 表示标签不需要放前缀,因为自定义的标签它原本就带好了前缀,所以不需要再添加;注释51 的代码表示通过系统标签创建 View,写 xml 布局时系统标签时没有前缀,所以这里创建 View 之前要添加标签前缀,我们看看一般常用的系统标签的前缀集合?sClassPrefixList 存放的数据;
我们一般常用的系统标签放在 widget、view 和 webkit 这3个包下面;我们看注释51、52 的代码,也就是?AppCompatViewInflater 的?createView(C-ontext context, String name, String prefix) 方法;
AppCompatViewInflater 的?createView(Context context, String name, String prefix) 方法最终通过反射机制创建一个 View 对象;如果在 xml 布局文件中写入一个不存在的标签(不是系统标签,也不是自定义标签),那么就会返回一个空的 View 对象。 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 14:08:28- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |